@itwin/ecschema-rpcinterface-tests 4.0.0-dev.4 → 4.0.0-dev.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/dist/_07c5.bundled-tests.js.map +1 -1
- package/lib/dist/bundled-tests.js +1709 -197
- 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 +16 -16
|
@@ -144037,15 +144037,6 @@ class Bundle {
|
|
|
144037
144037
|
return undefined;
|
|
144038
144038
|
}
|
|
144039
144039
|
const colorTextures = [];
|
|
144040
|
-
// Check if the system can render to a depth texture without a renderable color texture bound as well.
|
|
144041
|
-
// If it cannot, add a renderable color texture to the framebuffer.
|
|
144042
|
-
// MacOS Safari exhibited this behavior, which necessitated this code path.
|
|
144043
|
-
if (!_System__WEBPACK_IMPORTED_MODULE_13__.System.instance.canRenderDepthWithoutColor) {
|
|
144044
|
-
const colTex = _Texture__WEBPACK_IMPORTED_MODULE_14__.TextureHandle.createForAttachment(shadowMapWidth, shadowMapHeight, _GL__WEBPACK_IMPORTED_MODULE_8__.GL.Texture.Format.Rgba, pixelDataType);
|
|
144045
|
-
if (undefined === colTex)
|
|
144046
|
-
return undefined;
|
|
144047
|
-
colorTextures.push(colTex);
|
|
144048
|
-
}
|
|
144049
144040
|
const fbo = _FrameBuffer__WEBPACK_IMPORTED_MODULE_7__.FrameBuffer.create(colorTextures, depthTextureHandle);
|
|
144050
144041
|
if (undefined === fbo)
|
|
144051
144042
|
return undefined;
|
|
@@ -145080,7 +145071,6 @@ class System extends _RenderSystem__WEBPACK_IMPORTED_MODULE_7__.RenderSystem {
|
|
|
145080
145071
|
get maxTextureSize() { return this._capabilities.maxTextureSize; }
|
|
145081
145072
|
get supportsCreateImageBitmap() { return this._capabilities.supportsCreateImageBitmap; }
|
|
145082
145073
|
get maxRenderType() { return this._capabilities.maxRenderType; }
|
|
145083
|
-
get canRenderDepthWithoutColor() { return this._capabilities.canRenderDepthWithoutColor; }
|
|
145084
145074
|
get fragDepthDoesNotDisableEarlyZ() { return this._capabilities.driverBugs.fragDepthDoesNotDisableEarlyZ; }
|
|
145085
145075
|
get maxAntialiasSamples() { return this._capabilities.maxAntialiasSamples; }
|
|
145086
145076
|
get supportsNonPowerOf2Textures() { return this._capabilities.supportsNonPowerOf2Textures; }
|
|
@@ -165320,8 +165310,7 @@ class RealityTileTree extends _internal__WEBPACK_IMPORTED_MODULE_6__.TileTree {
|
|
|
165320
165310
|
if (imageryTiles.length)
|
|
165321
165311
|
this.logTiles("Imagery:", imageryTiles.values());
|
|
165322
165312
|
}
|
|
165323
|
-
|
|
165324
|
-
this.reportTileVisibility(args, selected);
|
|
165313
|
+
this.reportTileVisibility(args, selected);
|
|
165325
165314
|
_IModelApp__WEBPACK_IMPORTED_MODULE_4__.IModelApp.tileAdmin.addTilesForUser(args.context.viewport, selected, args.readyTiles);
|
|
165326
165315
|
return selected;
|
|
165327
165316
|
}
|
|
@@ -171589,16 +171578,21 @@ class ImageryMapTile extends _internal__WEBPACK_IMPORTED_MODULE_4__.RealityTile
|
|
|
171589
171578
|
this.parent.setLeaf(); // Avoid traversing bing branches after no graphics is found.
|
|
171590
171579
|
this.setIsReady();
|
|
171591
171580
|
}
|
|
171592
|
-
selectCartoDrapeTiles(drapeTiles, rectangleToDrape, drapePixelSize, args) {
|
|
171581
|
+
selectCartoDrapeTiles(drapeTiles, highResolutionReplacementTiles, rectangleToDrape, drapePixelSize, args) {
|
|
171593
171582
|
// Base draping overlap on width rather than height so that tiling schemes with multiple root nodes overlay correctly.
|
|
171594
171583
|
const isSmallerThanDrape = (this.rectangle.xLength() / this.maximumSize) < drapePixelSize;
|
|
171595
|
-
if (this.isLeaf // Include leaves so tiles get stretched past max LOD levels.
|
|
171584
|
+
if ((this.isLeaf) // Include leaves so tiles get stretched past max LOD levels. (Only for base imagery layer)
|
|
171596
171585
|
|| isSmallerThanDrape
|
|
171597
171586
|
|| this._anyChildNotFound) {
|
|
171598
171587
|
if (this.isOutOfLodRange) {
|
|
171599
171588
|
drapeTiles.push(this);
|
|
171600
171589
|
this.setIsReady();
|
|
171601
171590
|
}
|
|
171591
|
+
else if (this.isLeaf && !isSmallerThanDrape && !this._anyChildNotFound) {
|
|
171592
|
+
// These tiles are selected because we are beyond the max LOD of the tile tree,
|
|
171593
|
+
// might be used to display "stretched" tiles instead of having blank.
|
|
171594
|
+
highResolutionReplacementTiles.push(this);
|
|
171595
|
+
}
|
|
171602
171596
|
else {
|
|
171603
171597
|
drapeTiles.push(this);
|
|
171604
171598
|
}
|
|
@@ -171613,7 +171607,7 @@ class ImageryMapTile extends _internal__WEBPACK_IMPORTED_MODULE_4__.RealityTile
|
|
|
171613
171607
|
for (const child of this.children) {
|
|
171614
171608
|
const mapChild = child;
|
|
171615
171609
|
if (mapChild.rectangle.intersectsRange(rectangleToDrape))
|
|
171616
|
-
status = mapChild.selectCartoDrapeTiles(drapeTiles, rectangleToDrape, drapePixelSize, args);
|
|
171610
|
+
status = mapChild.selectCartoDrapeTiles(drapeTiles, highResolutionReplacementTiles, rectangleToDrape, drapePixelSize, args);
|
|
171617
171611
|
if (_internal__WEBPACK_IMPORTED_MODULE_4__.TileTreeLoadStatus.Loaded !== status)
|
|
171618
171612
|
break;
|
|
171619
171613
|
}
|
|
@@ -171748,12 +171742,12 @@ class ImageryMapTileTree extends _internal__WEBPACK_IMPORTED_MODULE_4__.RealityT
|
|
|
171748
171742
|
return [];
|
|
171749
171743
|
}
|
|
171750
171744
|
draw(_args) { (0,_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.assert)(false); }
|
|
171751
|
-
selectCartoDrapeTiles(drapeTiles, tileToDrape, args) {
|
|
171745
|
+
selectCartoDrapeTiles(drapeTiles, highResolutionReplacementTiles, tileToDrape, args) {
|
|
171752
171746
|
const drapeRectangle = tileToDrape.rectangle.clone(ImageryMapTileTree._scratchDrapeRectangle);
|
|
171753
171747
|
// Base draping overlap on width rather than height so that tiling schemes with multiple root nodes overlay correctly.
|
|
171754
171748
|
const drapePixelSize = 1.05 * tileToDrape.rectangle.xLength() / tileToDrape.maximumSize;
|
|
171755
171749
|
drapeRectangle.scaleAboutCenterInPlace(ImageryMapTileTree._drapeIntersectionScale); // Contract slightly to avoid draping adjacent or slivers.
|
|
171756
|
-
return this.rootTile.selectCartoDrapeTiles(drapeTiles, drapeRectangle, drapePixelSize, args);
|
|
171750
|
+
return this.rootTile.selectCartoDrapeTiles(drapeTiles, highResolutionReplacementTiles, drapeRectangle, drapePixelSize, args);
|
|
171757
171751
|
}
|
|
171758
171752
|
cartoRectangleFromQuadId(quadId) { return this.tilingScheme.tileXYToRectangle(quadId.column, quadId.row, quadId.level); }
|
|
171759
171753
|
}
|
|
@@ -173112,6 +173106,13 @@ class MapTile extends _internal__WEBPACK_IMPORTED_MODULE_7__.RealityTile {
|
|
|
173112
173106
|
* @internal
|
|
173113
173107
|
*/
|
|
173114
173108
|
get hiddenImageryTiles() { return this._hiddenTiles; }
|
|
173109
|
+
/** List of leafs tiles that have been selected as a replacement for missing high resolution tiles.
|
|
173110
|
+
* When this list is non-empty this means we are past the maximum LOD available of the tile tree.
|
|
173111
|
+
* By using those tiles, you are likely to get a display where tiles looks pixelated..
|
|
173112
|
+
* in some cases this is preferred to have no tile at all.
|
|
173113
|
+
* @internal
|
|
173114
|
+
*/
|
|
173115
|
+
get highResolutionReplacementTiles() { return this._highResolutionReplacementTiles; }
|
|
173115
173116
|
/** @internal */
|
|
173116
173117
|
getRangeCorners(result) {
|
|
173117
173118
|
return this._patch instanceof PlanarTilePatch ? this._patch.getRangeCorners(this.heightRange, result) : this.range.corners(result);
|
|
@@ -173384,6 +173385,9 @@ class MapTile extends _internal__WEBPACK_IMPORTED_MODULE_7__.RealityTile {
|
|
|
173384
173385
|
if (this._hiddenTiles) {
|
|
173385
173386
|
this._hiddenTiles = undefined;
|
|
173386
173387
|
}
|
|
173388
|
+
if (this._highResolutionReplacementTiles) {
|
|
173389
|
+
this._highResolutionReplacementTiles = undefined;
|
|
173390
|
+
}
|
|
173387
173391
|
}
|
|
173388
173392
|
/** @internal */
|
|
173389
173393
|
produceGraphics() {
|
|
@@ -173475,12 +173479,26 @@ class MapTile extends _internal__WEBPACK_IMPORTED_MODULE_7__.RealityTile {
|
|
|
173475
173479
|
this.clearImageryTiles();
|
|
173476
173480
|
this._imageryTiles = new Array();
|
|
173477
173481
|
this._hiddenTiles = new Array();
|
|
173482
|
+
this._highResolutionReplacementTiles = new Array();
|
|
173478
173483
|
for (const layerImageryTree of this.mapTree.layerImageryTrees) {
|
|
173479
|
-
|
|
173480
|
-
|
|
173484
|
+
let tmpTiles = new Array();
|
|
173485
|
+
const tmpLeafTiles = new Array();
|
|
173486
|
+
if (_internal__WEBPACK_IMPORTED_MODULE_7__.TileTreeLoadStatus.Loaded !== layerImageryTree.tree.selectCartoDrapeTiles(tmpTiles, tmpLeafTiles, this, args)) {
|
|
173481
173487
|
this._imageryTiles = undefined;
|
|
173482
173488
|
return;
|
|
173483
173489
|
}
|
|
173490
|
+
// When the base layer is zoomed-in beyond it's max resolution,
|
|
173491
|
+
// we display leaf tiles and stretched them if needed.
|
|
173492
|
+
// We don't want the same behavior non-base layers, in the case,
|
|
173493
|
+
// the layer will simply disappear past its max resolution.
|
|
173494
|
+
// Note: Replacement leaf tiles are kept as a mean to determine which
|
|
173495
|
+
// imagery tree has reached it's maximum zoom level.
|
|
173496
|
+
if (layerImageryTree.baseImageryLayer) {
|
|
173497
|
+
tmpTiles = [...tmpTiles, ...tmpLeafTiles];
|
|
173498
|
+
}
|
|
173499
|
+
else {
|
|
173500
|
+
this._highResolutionReplacementTiles = [...this._highResolutionReplacementTiles, ...tmpLeafTiles];
|
|
173501
|
+
}
|
|
173484
173502
|
// MapTileTree might include a non-visible imagery tree, we need to check for that.
|
|
173485
173503
|
if (layerImageryTree.settings.visible && !layerImageryTree.settings.allSubLayersInvisible) {
|
|
173486
173504
|
for (const imageryTile of tmpTiles) {
|
|
@@ -174138,8 +174156,8 @@ class MapTileTree extends _internal__WEBPACK_IMPORTED_MODULE_7__.RealityTileTree
|
|
|
174138
174156
|
/** Add a new imagery tile tree / map-layer settings pair and initialize the imagery tile tree state.
|
|
174139
174157
|
* @internal
|
|
174140
174158
|
*/
|
|
174141
|
-
addImageryLayer(tree, settings, index) {
|
|
174142
|
-
this.layerImageryTrees.push({ tree, settings });
|
|
174159
|
+
addImageryLayer(tree, settings, index, baseImageryLayer) {
|
|
174160
|
+
this.layerImageryTrees.push({ tree, settings, baseImageryLayer });
|
|
174143
174161
|
this._layerSettings.set(tree.modelId, settings);
|
|
174144
174162
|
if (!this._imageryTreeState.has(tree.modelId))
|
|
174145
174163
|
this._imageryTreeState.set(tree.modelId, new _internal__WEBPACK_IMPORTED_MODULE_7__.ImageryTileTreeState());
|
|
@@ -174378,15 +174396,19 @@ class MapTileTree extends _internal__WEBPACK_IMPORTED_MODULE_7__.RealityTileTree
|
|
|
174378
174396
|
treeVisibility.reset();
|
|
174379
174397
|
}
|
|
174380
174398
|
}
|
|
174381
|
-
let allTilesRead = true;
|
|
174382
174399
|
for (const selectedTile of selected) {
|
|
174383
174400
|
if (selectedTile instanceof _internal__WEBPACK_IMPORTED_MODULE_7__.MapTile) {
|
|
174384
|
-
if (!selectedTile.isReady)
|
|
174385
|
-
allTilesRead = false;
|
|
174386
174401
|
let selectedImageryTiles = selectedTile.imageryTiles;
|
|
174387
174402
|
if (selectedTile.hiddenImageryTiles) {
|
|
174388
174403
|
selectedImageryTiles = selectedImageryTiles ? [...selectedImageryTiles, ...selectedTile.hiddenImageryTiles] : selectedTile.hiddenImageryTiles;
|
|
174389
174404
|
}
|
|
174405
|
+
const leafTiles = selectedTile.highResolutionReplacementTiles;
|
|
174406
|
+
if (leafTiles) {
|
|
174407
|
+
for (const tile of leafTiles) {
|
|
174408
|
+
const treeState = this.getImageryTreeState(tile.tree.id);
|
|
174409
|
+
treeState === null || treeState === void 0 ? void 0 : treeState.setScaleRangeVisibility(false);
|
|
174410
|
+
}
|
|
174411
|
+
}
|
|
174390
174412
|
if (selectedImageryTiles) {
|
|
174391
174413
|
for (const selectedImageryTile of selectedImageryTiles) {
|
|
174392
174414
|
const treeState = this.getImageryTreeState(selectedImageryTile.tree.id);
|
|
@@ -174402,8 +174424,6 @@ class MapTileTree extends _internal__WEBPACK_IMPORTED_MODULE_7__.RealityTileTree
|
|
|
174402
174424
|
}
|
|
174403
174425
|
}
|
|
174404
174426
|
}
|
|
174405
|
-
if (!allTilesRead)
|
|
174406
|
-
changes;
|
|
174407
174427
|
for (const [treeId, prevState] of layersVisibilityBefore) {
|
|
174408
174428
|
const newState = this.getImageryTreeState(treeId);
|
|
174409
174429
|
if (newState) {
|
|
@@ -174780,8 +174800,9 @@ class MapTileTreeReference extends _internal__WEBPACK_IMPORTED_MODULE_7__.TileTr
|
|
|
174780
174800
|
const layerTree = layerTreeRef.treeOwner.load();
|
|
174781
174801
|
if (undefined === layerTree)
|
|
174782
174802
|
return false; // Not loaded yet.
|
|
174803
|
+
const baseImageryLayer = this._baseImageryLayerIncluded && (treeIndex === 0);
|
|
174783
174804
|
if (layerTree instanceof _internal__WEBPACK_IMPORTED_MODULE_7__.ImageryMapTileTree) {
|
|
174784
|
-
tree.addImageryLayer(layerTree, layerTreeRef.layerSettings, treeIndex);
|
|
174805
|
+
tree.addImageryLayer(layerTree, layerTreeRef.layerSettings, treeIndex, baseImageryLayer);
|
|
174785
174806
|
}
|
|
174786
174807
|
else if (layerTreeRef instanceof _internal__WEBPACK_IMPORTED_MODULE_7__.ModelMapLayerTileTreeReference)
|
|
174787
174808
|
tree.addModelLayer(layerTreeRef, context);
|
|
@@ -201212,6 +201233,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
201212
201233
|
/* harmony export */ "NewtonEvaluatorRtoRD": () => (/* reexport safe */ _numerics_Newton__WEBPACK_IMPORTED_MODULE_51__.NewtonEvaluatorRtoRD),
|
|
201213
201234
|
/* harmony export */ "NullGeometryHandler": () => (/* reexport safe */ _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODULE_8__.NullGeometryHandler),
|
|
201214
201235
|
/* harmony export */ "NumberArray": () => (/* reexport safe */ _geometry3d_PointHelpers__WEBPACK_IMPORTED_MODULE_23__.NumberArray),
|
|
201236
|
+
/* harmony export */ "OffsetMeshOptions": () => (/* reexport safe */ _polyface_PolyfaceQuery__WEBPACK_IMPORTED_MODULE_116__.OffsetMeshOptions),
|
|
201215
201237
|
/* harmony export */ "OffsetOptions": () => (/* reexport safe */ _curve_internalContexts_PolygonOffsetContext__WEBPACK_IMPORTED_MODULE_79__.OffsetOptions),
|
|
201216
201238
|
/* harmony export */ "Order2Bezier": () => (/* reexport safe */ _numerics_BezierPolynomials__WEBPACK_IMPORTED_MODULE_49__.Order2Bezier),
|
|
201217
201239
|
/* harmony export */ "Order3Bezier": () => (/* reexport safe */ _numerics_BezierPolynomials__WEBPACK_IMPORTED_MODULE_49__.Order3Bezier),
|
|
@@ -203609,6 +203631,10 @@ class CurveChainWithDistanceIndex extends _curve_CurvePrimitive__WEBPACK_IMPORTE
|
|
|
203609
203631
|
const fragment = this.chainDistanceToFragment(distanceAlongPath, true);
|
|
203610
203632
|
const curveFraction = fragment.chainDistanceToAccurateChildFraction(distanceAlongPath, true);
|
|
203611
203633
|
result = fragment.childCurve.fractionToPointAndDerivative(curveFraction, result);
|
|
203634
|
+
// Fractional arc length parameterization for the curve C is f=f(t)=s(t)/L, where
|
|
203635
|
+
// L is total length of C, f'=||C'||/L, and inverse t=t(f), t'=1/f'=L/||C'||.
|
|
203636
|
+
// Then d/df(C(t(f)))=C't'=C'L/||C'||. The fragment gave us C', so the
|
|
203637
|
+
// derivative we seek is just a scale away.
|
|
203612
203638
|
const a = this._totalLength / result.direction.magnitude();
|
|
203613
203639
|
result.direction.scaleInPlace(a);
|
|
203614
203640
|
return result;
|
|
@@ -203634,23 +203660,26 @@ class CurveChainWithDistanceIndex extends _curve_CurvePrimitive__WEBPACK_IMPORTE
|
|
|
203634
203660
|
* * vectorV is the second derivative, i.e.derivative of vectorU.
|
|
203635
203661
|
*/
|
|
203636
203662
|
fractionToPointAnd2Derivatives(fraction, result) {
|
|
203637
|
-
const
|
|
203638
|
-
const distanceAlongPath = fraction * totalLength;
|
|
203663
|
+
const distanceAlongPath = fraction * this._totalLength;
|
|
203639
203664
|
const fragment = this.chainDistanceToFragment(distanceAlongPath, true);
|
|
203640
203665
|
const curveFraction = fragment.chainDistanceToAccurateChildFraction(distanceAlongPath, true);
|
|
203641
203666
|
result = fragment.childCurve.fractionToPointAnd2Derivatives(curveFraction, result);
|
|
203642
203667
|
if (!result)
|
|
203643
203668
|
return undefined;
|
|
203644
|
-
|
|
203645
|
-
|
|
203669
|
+
// See fractionToPointAndDerivative for derivation of d/df(C(t(f)))=L C'/||C'||.
|
|
203670
|
+
// For the 2nd deriv, use quotient rule, d/dt||x(t)||=x.x'/||x|| and ||x||^2=x.x :
|
|
203671
|
+
// d/df(C'(t(f))) = L d/df(C'/||C'||)
|
|
203672
|
+
// = L (||C'|| d/df(C') - C' d/df||C'||) / ||C'||^2
|
|
203673
|
+
// = L (||C'|| C" L/||C'|| - C' C'.C"/||C'|| L/||C'||) / ||C'||^2
|
|
203674
|
+
// = (L/||C'||)^2 (C" - C' C'.C"/C'.C' )
|
|
203675
|
+
// We have C' and C" from the fragment.
|
|
203676
|
+
const magU = result.vectorU.magnitude();
|
|
203677
|
+
const dotUU = magU * magU;
|
|
203646
203678
|
const dotUV = result.vectorU.dotProduct(result.vectorV);
|
|
203647
|
-
|
|
203648
|
-
const
|
|
203649
|
-
|
|
203650
|
-
result.
|
|
203651
|
-
// scale for 0..1 parameterization ....
|
|
203652
|
-
result.vectorU.scaleInPlace(totalLength);
|
|
203653
|
-
result.vectorV.scaleInPlace(totalLength * totalLength);
|
|
203679
|
+
result.vectorV.addScaledInPlace(result.vectorU, -dotUV / dotUU);
|
|
203680
|
+
const scale = this._totalLength / magU;
|
|
203681
|
+
result.vectorU.scaleInPlace(scale);
|
|
203682
|
+
result.vectorV.scaleInPlace(scale * scale);
|
|
203654
203683
|
return result;
|
|
203655
203684
|
}
|
|
203656
203685
|
/** Attempt to transform in place.
|
|
@@ -203715,7 +203744,7 @@ class CurveChainWithDistanceIndex extends _curve_CurvePrimitive__WEBPACK_IMPORTE
|
|
|
203715
203744
|
numCalls: this._numCalls,
|
|
203716
203745
|
numTested: this._numTested,
|
|
203717
203746
|
numAssigned: this._numAssigned,
|
|
203718
|
-
numCandidate: this._numCandidate
|
|
203747
|
+
numCandidate: this._numCandidate,
|
|
203719
203748
|
};
|
|
203720
203749
|
if (clear) {
|
|
203721
203750
|
this._numTested = this._numAssigned = this._numCandidate = 0;
|
|
@@ -219600,6 +219629,44 @@ class Angle {
|
|
|
219600
219629
|
const uDotV = ux * vx + uy * vy + uz * vz;
|
|
219601
219630
|
return Math.atan2(_Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.crossProductMagnitude(ux, uy, uz, vx, vy, vz), uDotV);
|
|
219602
219631
|
}
|
|
219632
|
+
/**
|
|
219633
|
+
* * Returns the angle between two vectors, with the vectors given as xyz components, and an up vector to resolve angle to a full 2PI range.
|
|
219634
|
+
* * The returned angle is (-PI < radians <= PI) or (0 <= radians < 2 * PI)
|
|
219635
|
+
* * The angle is in the plane of the U and V vectors.
|
|
219636
|
+
* * The upVector determines a positive side of the plane but need not be strictly perpendicular to the plane.
|
|
219637
|
+
*
|
|
219638
|
+
* @param ux x component of vector u
|
|
219639
|
+
* @param uy y component of vector u
|
|
219640
|
+
* @param uz z component of vector u
|
|
219641
|
+
* @param vx x component of vector v
|
|
219642
|
+
* @param vy y component of vector v
|
|
219643
|
+
* @param vz z component of vector v
|
|
219644
|
+
* @param upVectorX x component of vector to positive side of plane.
|
|
219645
|
+
* @param upVectorY y component of vector to positive side of plane.
|
|
219646
|
+
* @param upVectorZ z component of vector to positive side of plane.
|
|
219647
|
+
* @param adjustToAllPositive if true, return strictly non-negative sweep (0 <= radians < 2*PI). If false, return signed (-PI < radians <= PI)
|
|
219648
|
+
*/
|
|
219649
|
+
static orientedRadiansBetweenVectorsXYZ(ux, uy, uz, vx, vy, vz, upVectorX, upVectorY, upVectorZ, adjustToPositive = false) {
|
|
219650
|
+
const uDotV = ux * vx + uy * vy + uz * vz;
|
|
219651
|
+
const wx = uy * vz - uz * vy;
|
|
219652
|
+
const wy = uz * vx - ux * vz;
|
|
219653
|
+
const wz = ux * vy - uy * vx;
|
|
219654
|
+
const upDotW = upVectorX * wx + upVectorY * wy + upVectorZ * wz;
|
|
219655
|
+
const crossMagnitude = _Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.hypotenuseXYZ(wx, wy, wz);
|
|
219656
|
+
if (upDotW < 0.0) {
|
|
219657
|
+
if (adjustToPositive) {
|
|
219658
|
+
// The turn is greater than 180 degrees. Take a peculiarly oriented atan2 to get the excess-180 part as addition to PI.
|
|
219659
|
+
// This gives the smoothest numerical transition passing PI.
|
|
219660
|
+
return Math.PI + Math.atan2(crossMagnitude, -uDotV);
|
|
219661
|
+
}
|
|
219662
|
+
else {
|
|
219663
|
+
return -Math.atan2(crossMagnitude, uDotV);
|
|
219664
|
+
}
|
|
219665
|
+
}
|
|
219666
|
+
else {
|
|
219667
|
+
return Math.atan2(crossMagnitude, uDotV);
|
|
219668
|
+
}
|
|
219669
|
+
}
|
|
219603
219670
|
/**
|
|
219604
219671
|
* Add a multiple of a full circle angle (360 degrees, 2PI) in place.
|
|
219605
219672
|
* @param multiple multiplier factor
|
|
@@ -229300,9 +229367,12 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
229300
229367
|
* @module CartesianGeometry
|
|
229301
229368
|
*/
|
|
229302
229369
|
// cspell:word CWXY
|
|
229370
|
+
// cspell:word arctan
|
|
229371
|
+
// cspell:word Rodrigues
|
|
229303
229372
|
|
|
229304
229373
|
|
|
229305
229374
|
|
|
229375
|
+
// cspell:word CCWXY
|
|
229306
229376
|
/**
|
|
229307
229377
|
* * `XYZ` is a minimal object containing x,y,z and operations that are meaningful without change in both point and vector.
|
|
229308
229378
|
* * `XYZ` is not instantiable.
|
|
@@ -230645,18 +230715,17 @@ class Vector3d extends XYZ {
|
|
|
230645
230715
|
else
|
|
230646
230716
|
return theta;
|
|
230647
230717
|
}
|
|
230648
|
-
/**
|
|
230649
|
-
|
|
230650
|
-
|
|
230651
|
-
|
|
230652
|
-
|
|
230653
|
-
|
|
230654
|
-
|
|
230655
|
-
|
|
230656
|
-
|
|
230657
|
-
|
|
230658
|
-
|
|
230659
|
-
*/
|
|
230718
|
+
/** Return the (strongly typed Angle) angle from this vector to vectorB, measured in the plane containing both,
|
|
230719
|
+
* with vectorW indicating which side to view to control sign of the angle.
|
|
230720
|
+
* * The returned angle can range from negative 180 degrees (negative PI radians) to positive 180 degrees
|
|
230721
|
+
* * (positive PI radians), not closed on the negative side.
|
|
230722
|
+
* * The returned angle is "in the plane containing the two vectors"
|
|
230723
|
+
* * `vectorW` distinguishes between the sides of the plane, but does not have to be perpendicular.
|
|
230724
|
+
* * The returned angle has the same sign as vectorW dot product (thisVector cross vectorB)
|
|
230725
|
+
* * Use planarRadiansTo to measure the angle between vectors that are projected to another plane.
|
|
230726
|
+
* @param vectorB target vector.
|
|
230727
|
+
* @param vectorW distinguishes between the sides of the plane.
|
|
230728
|
+
*/
|
|
230660
230729
|
signedAngleTo(vectorB, vectorW) {
|
|
230661
230730
|
return _Angle__WEBPACK_IMPORTED_MODULE_2__.Angle.createRadians(this.signedRadiansTo(vectorB, vectorW));
|
|
230662
230731
|
}
|
|
@@ -243393,6 +243462,20 @@ class SmallSystem {
|
|
|
243393
243462
|
}
|
|
243394
243463
|
return undefined;
|
|
243395
243464
|
}
|
|
243465
|
+
/**
|
|
243466
|
+
* Compute the intersection of three planes.
|
|
243467
|
+
* @param xyzA point on the first plane
|
|
243468
|
+
* @param normalA normal of the first plane
|
|
243469
|
+
* @param xyzB point on the second plane
|
|
243470
|
+
* @param normalB normal of the second plane
|
|
243471
|
+
* @param xyzC point on the third plane
|
|
243472
|
+
* @param normalC normal of the third plane
|
|
243473
|
+
* @param result optional result
|
|
243474
|
+
* @returns intersection point of the three planes (as a Vector3d), or undefined if at least two planes are parallel.
|
|
243475
|
+
*/
|
|
243476
|
+
static intersect3Planes(xyzA, normalA, xyzB, normalB, xyzC, normalC, result) {
|
|
243477
|
+
return this.linearSystem3d(normalA.x, normalA.y, normalA.z, normalB.x, normalB.y, normalB.z, normalC.x, normalC.y, normalC.z, _Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.dotProductXYZXYZ(xyzA.x, xyzA.y, xyzA.z, normalA.x, normalA.y, normalA.z), _Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.dotProductXYZXYZ(xyzB.x, xyzB.y, xyzB.z, normalB.x, normalB.y, normalB.z), _Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.dotProductXYZXYZ(xyzC.x, xyzC.y, xyzC.z, normalC.x, normalC.y, normalC.z), result);
|
|
243478
|
+
}
|
|
243396
243479
|
/**
|
|
243397
243480
|
* * in rowB, replace `rowB[j] += a * rowB[pivot] * rowA[j] / rowA[pivot]` for `j>pivot`
|
|
243398
243481
|
* @param rowA row that does not change
|
|
@@ -247504,10 +247587,29 @@ class PolyfaceBuilder extends _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODU
|
|
|
247504
247587
|
if (sector.uv)
|
|
247505
247588
|
sector.uvIndex = this._polyface.addParam(sector.uv);
|
|
247506
247589
|
}
|
|
247590
|
+
addSectorTriangle(sectorA0, sectorA1, sectorA2) {
|
|
247591
|
+
if (sectorA0.xyz.isAlmostEqual(sectorA1.xyz)
|
|
247592
|
+
|| sectorA1.xyz.isAlmostEqual(sectorA2.xyz)
|
|
247593
|
+
|| sectorA2.xyz.isAlmostEqual(sectorA0.xyz)) {
|
|
247594
|
+
// trivially degenerate triangle !!! skip !!!
|
|
247595
|
+
}
|
|
247596
|
+
else {
|
|
247597
|
+
if (this._options.needNormals)
|
|
247598
|
+
this.addIndexedTriangleNormalIndexes(sectorA0.normalIndex, sectorA1.normalIndex, sectorA2.normalIndex);
|
|
247599
|
+
if (this._options.needParams)
|
|
247600
|
+
this.addIndexedTriangleParamIndexes(sectorA0.uvIndex, sectorA1.uvIndex, sectorA2.uvIndex);
|
|
247601
|
+
this.addIndexedTrianglePointIndexes(sectorA0.xyzIndex, sectorA1.xyzIndex, sectorA2.xyzIndex);
|
|
247602
|
+
this._polyface.terminateFacet();
|
|
247603
|
+
}
|
|
247604
|
+
}
|
|
247507
247605
|
addSectorQuadA01B01(sectorA0, sectorA1, sectorB0, sectorB1) {
|
|
247508
247606
|
if (sectorA0.xyz.isAlmostEqual(sectorA1.xyz) && sectorB0.xyz.isAlmostEqual(sectorB1.xyz)) {
|
|
247509
247607
|
// ignore null quad !!
|
|
247510
247608
|
}
|
|
247609
|
+
else if (this._options.shouldTriangulate) {
|
|
247610
|
+
this.addSectorTriangle(sectorA0, sectorA1, sectorB1);
|
|
247611
|
+
this.addSectorTriangle(sectorB1, sectorB0, sectorA0);
|
|
247612
|
+
}
|
|
247511
247613
|
else {
|
|
247512
247614
|
if (this._options.needNormals)
|
|
247513
247615
|
this.addIndexedQuadNormalIndexes(sectorA0.normalIndex, sectorA1.normalIndex, sectorB0.normalIndex, sectorB1.normalIndex);
|
|
@@ -247584,12 +247686,30 @@ class PolyfaceBuilder extends _geometry3d_GeometryHandler__WEBPACK_IMPORTED_MODU
|
|
|
247584
247686
|
}
|
|
247585
247687
|
const numPoints = pointA.length;
|
|
247586
247688
|
for (let i = 1; i < numPoints; i++) {
|
|
247587
|
-
if (
|
|
247588
|
-
|
|
247589
|
-
|
|
247590
|
-
|
|
247591
|
-
|
|
247592
|
-
|
|
247689
|
+
if (this.options.shouldTriangulate) {
|
|
247690
|
+
if (distinctIndices(pointA.atUncheckedIndex(i - 1), pointA.atUncheckedIndex(i), pointB.atUncheckedIndex(i))) {
|
|
247691
|
+
this.addIndexedTrianglePointIndexes(pointA.atUncheckedIndex(i - 1), pointA.atUncheckedIndex(i), pointB.atUncheckedIndex(i));
|
|
247692
|
+
if (normalA && normalB)
|
|
247693
|
+
this.addIndexedTriangleNormalIndexes(normalA.atUncheckedIndex(i - 1), normalA.atUncheckedIndex(i), normalB.atUncheckedIndex(i - 1));
|
|
247694
|
+
if (paramA && paramB)
|
|
247695
|
+
this.addIndexedTriangleParamIndexes(paramA.atUncheckedIndex(i - 1), paramA.atUncheckedIndex(i), paramB.atUncheckedIndex(i - 1));
|
|
247696
|
+
}
|
|
247697
|
+
if (distinctIndices(pointB.atUncheckedIndex(i), pointB.atUncheckedIndex(i - 1), pointA.atUncheckedIndex(i - 1))) {
|
|
247698
|
+
this.addIndexedTrianglePointIndexes(pointA.atUncheckedIndex(i - 1), pointB.atUncheckedIndex(i), pointB.atUncheckedIndex(i - 1));
|
|
247699
|
+
if (normalA && normalB)
|
|
247700
|
+
this.addIndexedTriangleNormalIndexes(normalA.atUncheckedIndex(i - 1), normalB.atUncheckedIndex(i), normalB.atUncheckedIndex(i - 1));
|
|
247701
|
+
if (paramA && paramB)
|
|
247702
|
+
this.addIndexedTriangleParamIndexes(paramA.atUncheckedIndex(i - 1), paramB.atUncheckedIndex(i), paramB.atUncheckedIndex(i - 1));
|
|
247703
|
+
}
|
|
247704
|
+
}
|
|
247705
|
+
else {
|
|
247706
|
+
if (pointA.atUncheckedIndex(i - 1) !== pointA.atUncheckedIndex(i) || pointB.atUncheckedIndex(i - 1) !== pointB.atUncheckedIndex(i)) {
|
|
247707
|
+
this.addIndexedQuadPointIndexes(pointA.atUncheckedIndex(i - 1), pointA.atUncheckedIndex(i), pointB.atUncheckedIndex(i - 1), pointB.atUncheckedIndex(i));
|
|
247708
|
+
if (normalA && normalB)
|
|
247709
|
+
this.addIndexedQuadNormalIndexes(normalA.atUncheckedIndex(i - 1), normalA.atUncheckedIndex(i), normalB.atUncheckedIndex(i - 1), normalB.atUncheckedIndex(i));
|
|
247710
|
+
if (paramA && paramB)
|
|
247711
|
+
this.addIndexedQuadParamIndexes(paramA.atUncheckedIndex(i - 1), paramA.atUncheckedIndex(i), paramB.atUncheckedIndex(i - 1), paramB.atUncheckedIndex(i));
|
|
247712
|
+
}
|
|
247593
247713
|
this._polyface.terminateFacet();
|
|
247594
247714
|
}
|
|
247595
247715
|
}
|
|
@@ -248586,6 +248706,9 @@ function resolveToIndexedXYZCollectionOrCarrier(points) {
|
|
|
248586
248706
|
return points.packedPoints;
|
|
248587
248707
|
return points;
|
|
248588
248708
|
}
|
|
248709
|
+
function distinctIndices(i0, i1, i2) {
|
|
248710
|
+
return i0 !== i1 && i1 !== i2 && i2 !== i0;
|
|
248711
|
+
}
|
|
248589
248712
|
|
|
248590
248713
|
|
|
248591
248714
|
/***/ }),
|
|
@@ -249754,38 +249877,41 @@ function compressUnusedGrowableXYZArray(data: GrowableXYZArray, indices: number[
|
|
|
249754
249877
|
__webpack_require__.r(__webpack_exports__);
|
|
249755
249878
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
249756
249879
|
/* harmony export */ "DuplicateFacetClusterSelector": () => (/* binding */ DuplicateFacetClusterSelector),
|
|
249880
|
+
/* harmony export */ "OffsetMeshOptions": () => (/* binding */ OffsetMeshOptions),
|
|
249757
249881
|
/* harmony export */ "PolyfaceQuery": () => (/* binding */ PolyfaceQuery)
|
|
249758
249882
|
/* harmony export */ });
|
|
249759
249883
|
/* harmony import */ var _geometry3d_PointHelpers__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ../geometry3d/PointHelpers */ "../../core/geometry/lib/esm/geometry3d/PointHelpers.js");
|
|
249760
|
-
/* harmony import */ var
|
|
249884
|
+
/* harmony import */ var _curve_CurveCollection__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../curve/CurveCollection */ "../../core/geometry/lib/esm/curve/CurveCollection.js");
|
|
249761
249885
|
/* harmony import */ var _curve_internalContexts_MultiChainCollector__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ../curve/internalContexts/MultiChainCollector */ "../../core/geometry/lib/esm/curve/internalContexts/MultiChainCollector.js");
|
|
249762
|
-
/* harmony import */ var
|
|
249763
|
-
/* harmony import */ var
|
|
249764
|
-
/* harmony import */ var
|
|
249886
|
+
/* harmony import */ var _curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../curve/LineSegment3d */ "../../core/geometry/lib/esm/curve/LineSegment3d.js");
|
|
249887
|
+
/* harmony import */ var _curve_LineString3d__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../curve/LineString3d */ "../../core/geometry/lib/esm/curve/LineString3d.js");
|
|
249888
|
+
/* harmony import */ var _curve_Loop__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../curve/Loop */ "../../core/geometry/lib/esm/curve/Loop.js");
|
|
249765
249889
|
/* harmony import */ var _curve_StrokeOptions__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! ../curve/StrokeOptions */ "../../core/geometry/lib/esm/curve/StrokeOptions.js");
|
|
249766
|
-
/* harmony import */ var
|
|
249767
|
-
/* harmony import */ var
|
|
249890
|
+
/* harmony import */ var _Geometry__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../Geometry */ "../../core/geometry/lib/esm/Geometry.js");
|
|
249891
|
+
/* harmony import */ var _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../geometry3d/Angle */ "../../core/geometry/lib/esm/geometry3d/Angle.js");
|
|
249768
249892
|
/* harmony import */ var _geometry3d_FrameBuilder__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ../geometry3d/FrameBuilder */ "../../core/geometry/lib/esm/geometry3d/FrameBuilder.js");
|
|
249769
|
-
/* harmony import */ var
|
|
249770
|
-
/* harmony import */ var
|
|
249893
|
+
/* harmony import */ var _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../geometry3d/Point3dVector3d */ "../../core/geometry/lib/esm/geometry3d/Point3dVector3d.js");
|
|
249894
|
+
/* harmony import */ var _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../geometry3d/PolygonOps */ "../../core/geometry/lib/esm/geometry3d/PolygonOps.js");
|
|
249771
249895
|
/* harmony import */ var _geometry3d_Range__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(/*! ../geometry3d/Range */ "../../core/geometry/lib/esm/geometry3d/Range.js");
|
|
249772
|
-
/* harmony import */ var
|
|
249773
|
-
/* harmony import */ var
|
|
249774
|
-
/* harmony import */ var
|
|
249896
|
+
/* harmony import */ var _geometry4d_Matrix4d__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../geometry4d/Matrix4d */ "../../core/geometry/lib/esm/geometry4d/Matrix4d.js");
|
|
249897
|
+
/* harmony import */ var _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../geometry4d/MomentData */ "../../core/geometry/lib/esm/geometry4d/MomentData.js");
|
|
249898
|
+
/* harmony import */ var _numerics_UnionFind__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../numerics/UnionFind */ "../../core/geometry/lib/esm/numerics/UnionFind.js");
|
|
249775
249899
|
/* harmony import */ var _topology_ChainMerge__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! ../topology/ChainMerge */ "../../core/geometry/lib/esm/topology/ChainMerge.js");
|
|
249776
249900
|
/* harmony import */ var _topology_Graph__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ../topology/Graph */ "../../core/geometry/lib/esm/topology/Graph.js");
|
|
249777
249901
|
/* harmony import */ var _topology_HalfEdgeGraphSearch__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ../topology/HalfEdgeGraphSearch */ "../../core/geometry/lib/esm/topology/HalfEdgeGraphSearch.js");
|
|
249778
249902
|
/* harmony import */ var _topology_Merging__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ../topology/Merging */ "../../core/geometry/lib/esm/topology/Merging.js");
|
|
249779
|
-
/* harmony import */ var
|
|
249780
|
-
/* harmony import */ var
|
|
249903
|
+
/* harmony import */ var _FacetOrientation__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(/*! ./FacetOrientation */ "../../core/geometry/lib/esm/polyface/FacetOrientation.js");
|
|
249904
|
+
/* harmony import */ var _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./IndexedEdgeMatcher */ "../../core/geometry/lib/esm/polyface/IndexedEdgeMatcher.js");
|
|
249781
249905
|
/* harmony import */ var _IndexedPolyfaceVisitor__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./IndexedPolyfaceVisitor */ "../../core/geometry/lib/esm/polyface/IndexedPolyfaceVisitor.js");
|
|
249782
|
-
/* harmony import */ var
|
|
249783
|
-
/* harmony import */ var
|
|
249906
|
+
/* harmony import */ var _multiclip_BuildAverageNormalsContext__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(/*! ./multiclip/BuildAverageNormalsContext */ "../../core/geometry/lib/esm/polyface/multiclip/BuildAverageNormalsContext.js");
|
|
249907
|
+
/* harmony import */ var _multiclip_SweepLineStringToFacetContext__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./multiclip/SweepLineStringToFacetContext */ "../../core/geometry/lib/esm/polyface/multiclip/SweepLineStringToFacetContext.js");
|
|
249784
249908
|
/* harmony import */ var _multiclip_XYPointBuckets__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(/*! ./multiclip/XYPointBuckets */ "../../core/geometry/lib/esm/polyface/multiclip/XYPointBuckets.js");
|
|
249785
|
-
/* harmony import */ var
|
|
249909
|
+
/* harmony import */ var _Polyface__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./Polyface */ "../../core/geometry/lib/esm/polyface/Polyface.js");
|
|
249786
249910
|
/* harmony import */ var _PolyfaceBuilder__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./PolyfaceBuilder */ "../../core/geometry/lib/esm/polyface/PolyfaceBuilder.js");
|
|
249787
249911
|
/* harmony import */ var _RangeLengthData__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! ./RangeLengthData */ "../../core/geometry/lib/esm/polyface/RangeLengthData.js");
|
|
249788
249912
|
/* harmony import */ var _topology_SpaceTriangulation__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! ../topology/SpaceTriangulation */ "../../core/geometry/lib/esm/topology/SpaceTriangulation.js");
|
|
249913
|
+
/* harmony import */ var _topology_HalfEdgeGraphFromIndexedLoopsContext__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(/*! ../topology/HalfEdgeGraphFromIndexedLoopsContext */ "../../core/geometry/lib/esm/topology/HalfEdgeGraphFromIndexedLoopsContext.js");
|
|
249914
|
+
/* harmony import */ var _multiclip_OffsetMeshContext__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(/*! ./multiclip/OffsetMeshContext */ "../../core/geometry/lib/esm/polyface/multiclip/OffsetMeshContext.js");
|
|
249789
249915
|
/*---------------------------------------------------------------------------------------------
|
|
249790
249916
|
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
249791
249917
|
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
@@ -249825,6 +249951,41 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
249825
249951
|
|
|
249826
249952
|
|
|
249827
249953
|
|
|
249954
|
+
|
|
249955
|
+
|
|
249956
|
+
/**
|
|
249957
|
+
* Options carrier for [[PolyfaceQuery.cloneOffset]].
|
|
249958
|
+
* * Default options are strongly recommended.
|
|
249959
|
+
* * The option most likely to be changed is chamferTurnAngle
|
|
249960
|
+
* @public
|
|
249961
|
+
*/
|
|
249962
|
+
class OffsetMeshOptions {
|
|
249963
|
+
/** Constructor -- CAPTURE parameters ... */
|
|
249964
|
+
constructor(smoothSingleAngleBetweenNormals = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_0__.Angle.createDegrees(25), smoothAccumulatedAngleBetweenNormals = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_0__.Angle.createDegrees(60), chamferTurnAngle = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_0__.Angle.createDegrees(90)) {
|
|
249965
|
+
this.smoothSingleAngleBetweenNormals = smoothSingleAngleBetweenNormals.clone();
|
|
249966
|
+
this.smoothAccumulatedAngleBetweenNormals = smoothAccumulatedAngleBetweenNormals.clone();
|
|
249967
|
+
this.chamferAngleBetweenNormals = chamferTurnAngle.clone();
|
|
249968
|
+
}
|
|
249969
|
+
/** construct and return an OffsetMeshOptions with given parameters.
|
|
249970
|
+
* * Angles are forced to minimum values.
|
|
249971
|
+
* * Clones of the angles are given to the constructor.
|
|
249972
|
+
* @param smoothSingleRadiansBetweenNormals an angle larger than this (between facets) is considered a sharp edge
|
|
249973
|
+
* @param smoothAccumulatedAngleBetweenNormals angles that sum to this much may be consolidated for average normal
|
|
249974
|
+
* @param chamferTurnAngleBetweenNormals when facets meet with larger angle, a chamfer edge may be added if the angle between facet normals is larger than this.
|
|
249975
|
+
*/
|
|
249976
|
+
static create(smoothSingleAngleBetweenNormals = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_0__.Angle.createDegrees(25), smoothAccumulatedAngleBetweenNormals = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_0__.Angle.createDegrees(60), chamferTurnAngleBetweenNormals = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_0__.Angle.createDegrees(120)) {
|
|
249977
|
+
const mySmoothSingleRadiansBetweenNormals = smoothSingleAngleBetweenNormals.clone();
|
|
249978
|
+
const mySmoothAccumulatedRadiansBetweenNormals = smoothAccumulatedAngleBetweenNormals.clone();
|
|
249979
|
+
const myChamferTurnAngleBetweenNormals = chamferTurnAngleBetweenNormals.clone();
|
|
249980
|
+
if (mySmoothSingleRadiansBetweenNormals.degrees < 1)
|
|
249981
|
+
mySmoothAccumulatedRadiansBetweenNormals.setDegrees(1.0);
|
|
249982
|
+
if (mySmoothAccumulatedRadiansBetweenNormals.degrees < 1.0)
|
|
249983
|
+
mySmoothAccumulatedRadiansBetweenNormals.setDegrees(1.0);
|
|
249984
|
+
if (mySmoothAccumulatedRadiansBetweenNormals.degrees < 15.0)
|
|
249985
|
+
mySmoothAccumulatedRadiansBetweenNormals.setDegrees(15.0);
|
|
249986
|
+
return new OffsetMeshOptions(mySmoothSingleRadiansBetweenNormals, mySmoothAccumulatedRadiansBetweenNormals, myChamferTurnAngleBetweenNormals);
|
|
249987
|
+
}
|
|
249988
|
+
}
|
|
249828
249989
|
/**
|
|
249829
249990
|
* Enumeration of cases for retaining facets among duplicates
|
|
249830
249991
|
* @public
|
|
@@ -249846,12 +250007,12 @@ var DuplicateFacetClusterSelector;
|
|
|
249846
250007
|
class PolyfaceQuery {
|
|
249847
250008
|
/** copy the points from a visitor into a Linestring3d in a Loop object */
|
|
249848
250009
|
static visitorToLoop(visitor) {
|
|
249849
|
-
const ls =
|
|
249850
|
-
return
|
|
250010
|
+
const ls = _curve_LineString3d__WEBPACK_IMPORTED_MODULE_1__.LineString3d.createPoints(visitor.point.getPoint3dArray());
|
|
250011
|
+
return _curve_Loop__WEBPACK_IMPORTED_MODULE_2__.Loop.create(ls);
|
|
249851
250012
|
}
|
|
249852
250013
|
/** Create a linestring loop for each facet of the polyface. */
|
|
249853
250014
|
static indexedPolyfaceToLoops(polyface) {
|
|
249854
|
-
const result =
|
|
250015
|
+
const result = _curve_CurveCollection__WEBPACK_IMPORTED_MODULE_3__.BagOfCurves.create();
|
|
249855
250016
|
const visitor = polyface.createVisitor(1);
|
|
249856
250017
|
while (visitor.moveToNextFacet()) {
|
|
249857
250018
|
const loop = PolyfaceQuery.visitorToLoop(visitor);
|
|
@@ -249865,17 +250026,17 @@ class PolyfaceQuery {
|
|
|
249865
250026
|
static sumFacetAreas(source, vectorToEye) {
|
|
249866
250027
|
let s = 0;
|
|
249867
250028
|
if (source !== undefined) {
|
|
249868
|
-
if (source instanceof
|
|
250029
|
+
if (source instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface)
|
|
249869
250030
|
return PolyfaceQuery.sumFacetAreas(source.createVisitor(1), vectorToEye);
|
|
249870
250031
|
let unitVectorToEye;
|
|
249871
250032
|
if (vectorToEye !== undefined)
|
|
249872
250033
|
unitVectorToEye = vectorToEye.normalize();
|
|
249873
250034
|
source.reset();
|
|
249874
250035
|
while (source.moveToNextFacet()) {
|
|
249875
|
-
const scaledNormal =
|
|
250036
|
+
const scaledNormal = _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_5__.PolygonOps.areaNormal(source.point.getPoint3dArray());
|
|
249876
250037
|
let area = scaledNormal.magnitude();
|
|
249877
250038
|
if (unitVectorToEye !== undefined) {
|
|
249878
|
-
const scale =
|
|
250039
|
+
const scale = _Geometry__WEBPACK_IMPORTED_MODULE_6__.Geometry.conditionalDivideCoordinate(1.0, area);
|
|
249879
250040
|
if (scale !== undefined)
|
|
249880
250041
|
area *= scaledNormal.dotProduct(unitVectorToEye) * scale;
|
|
249881
250042
|
}
|
|
@@ -249892,12 +250053,12 @@ class PolyfaceQuery {
|
|
|
249892
250053
|
*/
|
|
249893
250054
|
static sumTetrahedralVolumes(source, origin) {
|
|
249894
250055
|
let s = 0;
|
|
249895
|
-
if (source instanceof
|
|
250056
|
+
if (source instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface)
|
|
249896
250057
|
return PolyfaceQuery.sumTetrahedralVolumes(source.createVisitor(0), origin);
|
|
249897
250058
|
let myOrigin = origin;
|
|
249898
|
-
const facetOrigin =
|
|
249899
|
-
const targetA =
|
|
249900
|
-
const targetB =
|
|
250059
|
+
const facetOrigin = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
|
|
250060
|
+
const targetA = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
|
|
250061
|
+
const targetB = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
|
|
249901
250062
|
source.reset();
|
|
249902
250063
|
while (source.moveToNextFacet()) {
|
|
249903
250064
|
if (myOrigin === undefined)
|
|
@@ -249918,20 +250079,20 @@ class PolyfaceQuery {
|
|
|
249918
250079
|
*
|
|
249919
250080
|
*/
|
|
249920
250081
|
static sumVolumeBetweenFacetsAndPlane(source, plane) {
|
|
249921
|
-
if (source instanceof
|
|
250082
|
+
if (source instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface)
|
|
249922
250083
|
return PolyfaceQuery.sumVolumeBetweenFacetsAndPlane(source.createVisitor(0), plane);
|
|
249923
|
-
const facetOrigin =
|
|
249924
|
-
const targetA =
|
|
249925
|
-
const targetB =
|
|
249926
|
-
const triangleNormal =
|
|
250084
|
+
const facetOrigin = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
|
|
250085
|
+
const targetA = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
|
|
250086
|
+
const targetB = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
|
|
250087
|
+
const triangleNormal = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Vector3d.create();
|
|
249927
250088
|
const planeNormal = plane.getNormalRef();
|
|
249928
250089
|
let h0, hA, hB;
|
|
249929
250090
|
let signedVolumeSum = 0.0;
|
|
249930
250091
|
let signedTriangleArea;
|
|
249931
250092
|
let singleFacetArea;
|
|
249932
|
-
const positiveAreaMomentSums =
|
|
249933
|
-
const negativeAreaMomentSums =
|
|
249934
|
-
const singleFacetProducts =
|
|
250093
|
+
const positiveAreaMomentSums = _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_8__.MomentData.create(undefined, true);
|
|
250094
|
+
const negativeAreaMomentSums = _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_8__.MomentData.create(undefined, true);
|
|
250095
|
+
const singleFacetProducts = _geometry4d_Matrix4d__WEBPACK_IMPORTED_MODULE_9__.Matrix4d.createZero();
|
|
249935
250096
|
const projectToPlane = plane.getProjectionToPlane();
|
|
249936
250097
|
source.reset();
|
|
249937
250098
|
// For each facet ..
|
|
@@ -249958,7 +250119,7 @@ class PolyfaceQuery {
|
|
|
249958
250119
|
}
|
|
249959
250120
|
singleFacetProducts.setZero();
|
|
249960
250121
|
source.point.multiplyTransformInPlace(projectToPlane);
|
|
249961
|
-
|
|
250122
|
+
_geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_5__.PolygonOps.addSecondMomentAreaProducts(source.point, facetOrigin, singleFacetProducts);
|
|
249962
250123
|
if (singleFacetArea > 0) {
|
|
249963
250124
|
positiveAreaMomentSums.accumulateProductsFromOrigin(facetOrigin, singleFacetProducts, 1.0);
|
|
249964
250125
|
}
|
|
@@ -249968,8 +250129,8 @@ class PolyfaceQuery {
|
|
|
249968
250129
|
}
|
|
249969
250130
|
positiveAreaMomentSums.shiftOriginAndSumsToCentroidOfSums();
|
|
249970
250131
|
negativeAreaMomentSums.shiftOriginAndSumsToCentroidOfSums();
|
|
249971
|
-
const positiveAreaMoments =
|
|
249972
|
-
const negativeAreaMoments =
|
|
250132
|
+
const positiveAreaMoments = _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_8__.MomentData.inertiaProductsToPrincipalAxes(positiveAreaMomentSums.origin, positiveAreaMomentSums.sums);
|
|
250133
|
+
const negativeAreaMoments = _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_8__.MomentData.inertiaProductsToPrincipalAxes(negativeAreaMomentSums.origin, negativeAreaMomentSums.sums);
|
|
249973
250134
|
return {
|
|
249974
250135
|
volume: signedVolumeSum / 6.0,
|
|
249975
250136
|
positiveProjectedFacetAreaMoments: positiveAreaMoments,
|
|
@@ -249978,23 +250139,23 @@ class PolyfaceQuery {
|
|
|
249978
250139
|
}
|
|
249979
250140
|
/** Return the inertia products [xx,xy,xz,xw, yw, etc] integrated over all all facets, as viewed from origin. */
|
|
249980
250141
|
static sumFacetSecondAreaMomentProducts(source, origin) {
|
|
249981
|
-
if (source instanceof
|
|
250142
|
+
if (source instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface)
|
|
249982
250143
|
return PolyfaceQuery.sumFacetSecondAreaMomentProducts(source.createVisitor(0), origin);
|
|
249983
|
-
const products =
|
|
250144
|
+
const products = _geometry4d_Matrix4d__WEBPACK_IMPORTED_MODULE_9__.Matrix4d.createZero();
|
|
249984
250145
|
source.reset();
|
|
249985
250146
|
while (source.moveToNextFacet()) {
|
|
249986
|
-
|
|
250147
|
+
_geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_5__.PolygonOps.addSecondMomentAreaProducts(source.point, origin, products);
|
|
249987
250148
|
}
|
|
249988
250149
|
return products;
|
|
249989
250150
|
}
|
|
249990
250151
|
/** Return the inertia products [xx,xy,xz,xw, yw, etc] integrated over all tetrahedral volumes from origin */
|
|
249991
250152
|
static sumFacetSecondVolumeMomentProducts(source, origin) {
|
|
249992
|
-
if (source instanceof
|
|
250153
|
+
if (source instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface)
|
|
249993
250154
|
return PolyfaceQuery.sumFacetSecondVolumeMomentProducts(source.createVisitor(0), origin);
|
|
249994
|
-
const products =
|
|
250155
|
+
const products = _geometry4d_Matrix4d__WEBPACK_IMPORTED_MODULE_9__.Matrix4d.createZero();
|
|
249995
250156
|
source.reset();
|
|
249996
250157
|
while (source.moveToNextFacet()) {
|
|
249997
|
-
|
|
250158
|
+
_geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_5__.PolygonOps.addSecondMomentVolumeProducts(source.point, origin, products);
|
|
249998
250159
|
}
|
|
249999
250160
|
return products;
|
|
250000
250161
|
}
|
|
@@ -250008,7 +250169,7 @@ class PolyfaceQuery {
|
|
|
250008
250169
|
if (!origin)
|
|
250009
250170
|
return undefined;
|
|
250010
250171
|
const inertiaProducts = PolyfaceQuery.sumFacetSecondAreaMomentProducts(source, origin);
|
|
250011
|
-
return
|
|
250172
|
+
return _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_8__.MomentData.inertiaProductsToPrincipalAxes(origin, inertiaProducts);
|
|
250012
250173
|
}
|
|
250013
250174
|
/** Compute area moments for the mesh. In the returned MomentData:
|
|
250014
250175
|
* * origin is the centroid.
|
|
@@ -250022,7 +250183,7 @@ class PolyfaceQuery {
|
|
|
250022
250183
|
if (!origin)
|
|
250023
250184
|
return undefined;
|
|
250024
250185
|
const inertiaProducts = PolyfaceQuery.sumFacetSecondVolumeMomentProducts(source, origin);
|
|
250025
|
-
return
|
|
250186
|
+
return _geometry4d_MomentData__WEBPACK_IMPORTED_MODULE_8__.MomentData.inertiaProductsToPrincipalAxes(origin, inertiaProducts);
|
|
250026
250187
|
}
|
|
250027
250188
|
/**
|
|
250028
250189
|
* Test for convex volume by dihedral angle tests on all edges.
|
|
@@ -250054,14 +250215,14 @@ class PolyfaceQuery {
|
|
|
250054
250215
|
* * (but null edges are permitted -- These occur naturally at edges of quads at north or south pole)
|
|
250055
250216
|
*/
|
|
250056
250217
|
static dihedralAngleSummary(source, ignoreBoundaries = false) {
|
|
250057
|
-
const edges = new
|
|
250218
|
+
const edges = new _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_10__.IndexedEdgeMatcher();
|
|
250058
250219
|
const visitor = source.createVisitor(1);
|
|
250059
250220
|
visitor.reset();
|
|
250060
250221
|
const centroidNormal = [];
|
|
250061
250222
|
let normalCounter = 0;
|
|
250062
250223
|
while (visitor.moveToNextFacet()) {
|
|
250063
250224
|
const numEdges = visitor.pointCount - 1;
|
|
250064
|
-
const normal =
|
|
250225
|
+
const normal = _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_5__.PolygonOps.centroidAreaNormal(visitor.point);
|
|
250065
250226
|
if (normal === undefined)
|
|
250066
250227
|
return 0;
|
|
250067
250228
|
centroidNormal.push(normal);
|
|
@@ -250078,12 +250239,12 @@ class PolyfaceQuery {
|
|
|
250078
250239
|
let numPositive = 0;
|
|
250079
250240
|
let numPlanar = 0;
|
|
250080
250241
|
let numNegative = 0;
|
|
250081
|
-
const edgeVector =
|
|
250242
|
+
const edgeVector = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Vector3d.create();
|
|
250082
250243
|
for (const cluster of manifoldClusters) {
|
|
250083
250244
|
const sideA = cluster[0];
|
|
250084
250245
|
const sideB = cluster[1];
|
|
250085
|
-
if (sideA instanceof
|
|
250086
|
-
&& sideB instanceof
|
|
250246
|
+
if (sideA instanceof _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_10__.SortableEdge
|
|
250247
|
+
&& sideB instanceof _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_10__.SortableEdge
|
|
250087
250248
|
&& source.data.point.vectorIndexIndex(sideA.vertexIndexA, sideA.vertexIndexB, edgeVector)) {
|
|
250088
250249
|
const dihedralAngle = centroidNormal[sideA.facetIndex].direction.signedAngleTo(centroidNormal[sideB.facetIndex].direction, edgeVector);
|
|
250089
250250
|
if (dihedralAngle.isAlmostZero)
|
|
@@ -250116,7 +250277,7 @@ class PolyfaceQuery {
|
|
|
250116
250277
|
* * Any edge with 2 incident facets in the same direction triggers a `false` return.
|
|
250117
250278
|
*/
|
|
250118
250279
|
static isPolyfaceManifold(source, allowSimpleBoundaries = false) {
|
|
250119
|
-
const edges = new
|
|
250280
|
+
const edges = new _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_10__.IndexedEdgeMatcher();
|
|
250120
250281
|
const visitor = source.createVisitor(1);
|
|
250121
250282
|
visitor.reset();
|
|
250122
250283
|
while (visitor.moveToNextFacet()) {
|
|
@@ -250139,9 +250300,9 @@ class PolyfaceQuery {
|
|
|
250139
250300
|
* @returns
|
|
250140
250301
|
*/
|
|
250141
250302
|
static boundaryEdges(source, includeDanglers = true, includeMismatch = true, includeNull = true) {
|
|
250142
|
-
const result = new
|
|
250303
|
+
const result = new _curve_CurveCollection__WEBPACK_IMPORTED_MODULE_3__.BagOfCurves();
|
|
250143
250304
|
const announceEdge = (pointA, pointB, _indexA, _indexB, _readIndex) => {
|
|
250144
|
-
result.tryAddChild(
|
|
250305
|
+
result.tryAddChild(_curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_11__.LineSegment3d.create(pointA, pointB));
|
|
250145
250306
|
};
|
|
250146
250307
|
PolyfaceQuery.announceBoundaryEdges(source, announceEdge, includeDanglers, includeMismatch, includeNull);
|
|
250147
250308
|
if (result.children.length === 0)
|
|
@@ -250160,8 +250321,8 @@ class PolyfaceQuery {
|
|
|
250160
250321
|
static announceBoundaryEdges(source, announceEdge, includeDanglers = true, includeMismatch = true, includeNull = true) {
|
|
250161
250322
|
if (source === undefined)
|
|
250162
250323
|
return undefined;
|
|
250163
|
-
const edges = new
|
|
250164
|
-
const visitor = source instanceof
|
|
250324
|
+
const edges = new _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_10__.IndexedEdgeMatcher();
|
|
250325
|
+
const visitor = source instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface ? source.createVisitor(1) : source;
|
|
250165
250326
|
visitor.setNumWrap(1);
|
|
250166
250327
|
visitor.reset();
|
|
250167
250328
|
while (visitor.moveToNextFacet()) {
|
|
@@ -250186,7 +250347,7 @@ class PolyfaceQuery {
|
|
|
250186
250347
|
const sourcePolyface = visitor.clientPolyface();
|
|
250187
250348
|
for (const list of badList) {
|
|
250188
250349
|
for (const e of list) {
|
|
250189
|
-
const e1 = e instanceof
|
|
250350
|
+
const e1 = e instanceof _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_10__.SortableEdge ? e : e[0];
|
|
250190
250351
|
const indexA = e1.vertexIndexA;
|
|
250191
250352
|
const indexB = e1.vertexIndexB;
|
|
250192
250353
|
const pointA = sourcePolyface.data.getPoint(indexA);
|
|
@@ -250201,7 +250362,7 @@ class PolyfaceQuery {
|
|
|
250201
250362
|
* * Facets are ASSUMED to be convex and planar.
|
|
250202
250363
|
*/
|
|
250203
250364
|
static announceSweepLinestringToConvexPolyfaceXY(linestringPoints, polyface, announce) {
|
|
250204
|
-
const context =
|
|
250365
|
+
const context = _multiclip_SweepLineStringToFacetContext__WEBPACK_IMPORTED_MODULE_12__.SweepLineStringToFacetContext.create(linestringPoints);
|
|
250205
250366
|
if (context) {
|
|
250206
250367
|
const visitor = polyface.createVisitor(0);
|
|
250207
250368
|
for (visitor.reset(); visitor.moveToNextFacet();) {
|
|
@@ -250234,7 +250395,7 @@ class PolyfaceQuery {
|
|
|
250234
250395
|
* @internal
|
|
250235
250396
|
*/
|
|
250236
250397
|
static async asyncAnnounceSweepLinestringToConvexPolyfaceXY(linestringPoints, polyface, announce) {
|
|
250237
|
-
const context =
|
|
250398
|
+
const context = _multiclip_SweepLineStringToFacetContext__WEBPACK_IMPORTED_MODULE_12__.SweepLineStringToFacetContext.create(linestringPoints);
|
|
250238
250399
|
this.awaitBlockCount = 0;
|
|
250239
250400
|
let workTotal = 0;
|
|
250240
250401
|
if (context) {
|
|
@@ -250254,11 +250415,11 @@ class PolyfaceQuery {
|
|
|
250254
250415
|
* * Return array of arrays of facet indices.
|
|
250255
250416
|
*/
|
|
250256
250417
|
static partitionFacetIndicesByVertexConnectedComponent(polyface) {
|
|
250257
|
-
if (polyface instanceof
|
|
250418
|
+
if (polyface instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface) {
|
|
250258
250419
|
return this.partitionFacetIndicesByVertexConnectedComponent(polyface.createVisitor(0));
|
|
250259
250420
|
}
|
|
250260
250421
|
// The polyface is really a visitor !!!
|
|
250261
|
-
const context = new
|
|
250422
|
+
const context = new _numerics_UnionFind__WEBPACK_IMPORTED_MODULE_13__.UnionFindContext(this.visitorClientPointCount(polyface));
|
|
250262
250423
|
for (polyface.reset(); polyface.moveToNextFacet();) {
|
|
250263
250424
|
const firstVertexIndexOnThisFacet = polyface.pointIndex[0];
|
|
250264
250425
|
for (const vertexIndex of polyface.pointIndex)
|
|
@@ -250291,7 +250452,7 @@ class PolyfaceQuery {
|
|
|
250291
250452
|
* * Return array of arrays of facet indices.
|
|
250292
250453
|
*/
|
|
250293
250454
|
static partitionFacetIndicesByVisibilityVector(polyface, vectorToEye, sideAngleTolerance) {
|
|
250294
|
-
if (polyface instanceof
|
|
250455
|
+
if (polyface instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface) {
|
|
250295
250456
|
return this.partitionFacetIndicesByVisibilityVector(polyface.createVisitor(0), vectorToEye, sideAngleTolerance);
|
|
250296
250457
|
}
|
|
250297
250458
|
const facetsInComponent = [];
|
|
@@ -250303,7 +250464,7 @@ class PolyfaceQuery {
|
|
|
250303
250464
|
const sideComponent = facetsInComponent[2];
|
|
250304
250465
|
const radiansTol = Math.max(sideAngleTolerance.radians, 1.0e-8);
|
|
250305
250466
|
for (polyface.reset(); polyface.moveToNextFacet();) {
|
|
250306
|
-
const areaNormal =
|
|
250467
|
+
const areaNormal = _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_5__.PolygonOps.areaNormalGo(polyface.point);
|
|
250307
250468
|
const index = polyface.currentReadIndex();
|
|
250308
250469
|
if (areaNormal) {
|
|
250309
250470
|
const angle = areaNormal.angleFromPerpendicular(vectorToEye);
|
|
@@ -250330,7 +250491,7 @@ class PolyfaceQuery {
|
|
|
250330
250491
|
* @param vectorToEye
|
|
250331
250492
|
* @param sideAngleTolerance
|
|
250332
250493
|
*/
|
|
250333
|
-
static boundaryOfVisibleSubset(polyface, visibilitySelect, vectorToEye, sideAngleTolerance =
|
|
250494
|
+
static boundaryOfVisibleSubset(polyface, visibilitySelect, vectorToEye, sideAngleTolerance = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_0__.Angle.createDegrees(1.0e-3)) {
|
|
250334
250495
|
const partitionedIndices = this.partitionFacetIndicesByVisibilityVector(polyface, vectorToEye, sideAngleTolerance);
|
|
250335
250496
|
if (partitionedIndices[visibilitySelect].length === 0)
|
|
250336
250497
|
return undefined;
|
|
@@ -250344,8 +250505,8 @@ class PolyfaceQuery {
|
|
|
250344
250505
|
* @param mesh
|
|
250345
250506
|
*/
|
|
250346
250507
|
static announceBoundaryChainsAsLineString3d(mesh, announceLoop) {
|
|
250347
|
-
const collector = new _curve_internalContexts_MultiChainCollector__WEBPACK_IMPORTED_MODULE_15__.MultiChainCollector(
|
|
250348
|
-
PolyfaceQuery.announceBoundaryEdges(mesh, (pointA, pointB, _indexA, _indexB) => collector.captureCurve(
|
|
250508
|
+
const collector = new _curve_internalContexts_MultiChainCollector__WEBPACK_IMPORTED_MODULE_15__.MultiChainCollector(_Geometry__WEBPACK_IMPORTED_MODULE_6__.Geometry.smallMetricDistance, 1000);
|
|
250509
|
+
PolyfaceQuery.announceBoundaryEdges(mesh, (pointA, pointB, _indexA, _indexB) => collector.captureCurve(_curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_11__.LineSegment3d.create(pointA, pointB)), true, false, false);
|
|
250349
250510
|
collector.announceChainsAsLineString3d(announceLoop);
|
|
250350
250511
|
}
|
|
250351
250512
|
/**
|
|
@@ -250356,7 +250517,7 @@ class PolyfaceQuery {
|
|
|
250356
250517
|
* @returns
|
|
250357
250518
|
*/
|
|
250358
250519
|
static cloneWithMaximalPlanarFacets(mesh) {
|
|
250359
|
-
if (mesh instanceof
|
|
250520
|
+
if (mesh instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface)
|
|
250360
250521
|
return this.cloneWithMaximalPlanarFacets(mesh.createVisitor(0));
|
|
250361
250522
|
const numFacets = PolyfaceQuery.visitorClientFacetCount(mesh);
|
|
250362
250523
|
const smoothEdges = PolyfaceQuery.collectEdgesByDihedralAngle(mesh);
|
|
@@ -250381,7 +250542,7 @@ class PolyfaceQuery {
|
|
|
250381
250542
|
const edges = [];
|
|
250382
250543
|
const edgeStrings = [];
|
|
250383
250544
|
PolyfaceQuery.announceBoundaryEdges(fragment, (pointA, pointB, _indexA, _indexB) => {
|
|
250384
|
-
edges.push(
|
|
250545
|
+
edges.push(_curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_11__.LineSegment3d.create(pointA, pointB));
|
|
250385
250546
|
edgeStrings.push([pointA.clone(), pointB.clone()]);
|
|
250386
250547
|
});
|
|
250387
250548
|
const chains = _curve_internalContexts_MultiChainCollector__WEBPACK_IMPORTED_MODULE_15__.OffsetHelpers.collectChains(edges, gapTolerance, planarityTolerance);
|
|
@@ -250422,7 +250583,7 @@ class PolyfaceQuery {
|
|
|
250422
250583
|
* @returns
|
|
250423
250584
|
*/
|
|
250424
250585
|
static fillSimpleHoles(mesh, options, unfilledChains) {
|
|
250425
|
-
if (mesh instanceof
|
|
250586
|
+
if (mesh instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface)
|
|
250426
250587
|
return this.fillSimpleHoles(mesh.createVisitor(0), options, unfilledChains);
|
|
250427
250588
|
const builder = _PolyfaceBuilder__WEBPACK_IMPORTED_MODULE_16__.PolyfaceBuilder.create();
|
|
250428
250589
|
const chains = [];
|
|
@@ -250436,7 +250597,7 @@ class PolyfaceQuery {
|
|
|
250436
250597
|
rejected = true;
|
|
250437
250598
|
else if (options.maxPerimeter !== undefined && _geometry3d_PointHelpers__WEBPACK_IMPORTED_MODULE_21__.Point3dArray.sumEdgeLengths(points, false) > options.maxPerimeter)
|
|
250438
250599
|
rejected = true;
|
|
250439
|
-
else if (options.upVector !== undefined &&
|
|
250600
|
+
else if (options.upVector !== undefined && _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_5__.PolygonOps.sumTriangleAreasPerpendicularToUpVector(points, options.upVector) <= 0.0)
|
|
250440
250601
|
rejected = true;
|
|
250441
250602
|
if (!rejected && _topology_SpaceTriangulation__WEBPACK_IMPORTED_MODULE_22__.SpacePolygonTriangulation.triangulateSimplestSpaceLoop(points, (_loop, triangles) => {
|
|
250442
250603
|
for (const t of triangles)
|
|
@@ -250459,7 +250620,7 @@ class PolyfaceQuery {
|
|
|
250459
250620
|
*
|
|
250460
250621
|
*/
|
|
250461
250622
|
static clonePartitions(polyface, partitions) {
|
|
250462
|
-
if (polyface instanceof
|
|
250623
|
+
if (polyface instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface) {
|
|
250463
250624
|
return this.clonePartitions(polyface.createVisitor(0), partitions);
|
|
250464
250625
|
}
|
|
250465
250626
|
polyface.setNumWrap(0);
|
|
@@ -250483,7 +250644,7 @@ class PolyfaceQuery {
|
|
|
250483
250644
|
/** Clone facets that pass an filter function
|
|
250484
250645
|
*/
|
|
250485
250646
|
static cloneFiltered(source, filter) {
|
|
250486
|
-
if (source instanceof
|
|
250647
|
+
if (source instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface) {
|
|
250487
250648
|
return this.cloneFiltered(source.createVisitor(0), filter);
|
|
250488
250649
|
}
|
|
250489
250650
|
source.setNumWrap(0);
|
|
@@ -250535,9 +250696,9 @@ class PolyfaceQuery {
|
|
|
250535
250696
|
* @return collection of facet index arrays, one array per connected component
|
|
250536
250697
|
*/
|
|
250537
250698
|
static partitionFacetIndicesBySortableEdgeClusters(edgeClusters, numFacets) {
|
|
250538
|
-
const context = new
|
|
250699
|
+
const context = new _numerics_UnionFind__WEBPACK_IMPORTED_MODULE_13__.UnionFindContext(numFacets);
|
|
250539
250700
|
for (const cluster of edgeClusters) {
|
|
250540
|
-
if (cluster instanceof
|
|
250701
|
+
if (cluster instanceof _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_10__.SortableEdge) {
|
|
250541
250702
|
// this edge does not connect anywhere. Ignore it!!
|
|
250542
250703
|
}
|
|
250543
250704
|
else {
|
|
@@ -250569,11 +250730,11 @@ class PolyfaceQuery {
|
|
|
250569
250730
|
* @return collection of facet index arrays, one per connected component
|
|
250570
250731
|
*/
|
|
250571
250732
|
static partitionFacetIndicesByEdgeConnectedComponent(polyface, stopAtVisibleEdges = false) {
|
|
250572
|
-
if (polyface instanceof
|
|
250733
|
+
if (polyface instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface) {
|
|
250573
250734
|
return this.partitionFacetIndicesByEdgeConnectedComponent(polyface.createVisitor(0), stopAtVisibleEdges);
|
|
250574
250735
|
}
|
|
250575
250736
|
polyface.setNumWrap(1);
|
|
250576
|
-
const matcher = new
|
|
250737
|
+
const matcher = new _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_10__.IndexedEdgeMatcher();
|
|
250577
250738
|
polyface.reset();
|
|
250578
250739
|
let numFacets = 0;
|
|
250579
250740
|
while (polyface.moveToNextFacet()) {
|
|
@@ -250611,7 +250772,7 @@ class PolyfaceQuery {
|
|
|
250611
250772
|
static sweepLinestringToFacetsXYReturnLines(linestringPoints, polyface) {
|
|
250612
250773
|
const drapeGeometry = [];
|
|
250613
250774
|
this.announceSweepLinestringToConvexPolyfaceXY(linestringPoints, polyface, (_linestring, _segmentIndex, _polyface, _facetIndex, points, indexA, indexB) => {
|
|
250614
|
-
drapeGeometry.push(
|
|
250775
|
+
drapeGeometry.push(_curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_11__.LineSegment3d.create(points[indexA], points[indexB]));
|
|
250615
250776
|
});
|
|
250616
250777
|
return drapeGeometry;
|
|
250617
250778
|
}
|
|
@@ -250646,7 +250807,7 @@ class PolyfaceQuery {
|
|
|
250646
250807
|
* * Return statistical summary of x,y,z ranges.
|
|
250647
250808
|
*/
|
|
250648
250809
|
static collectRangeLengthData(polyface) {
|
|
250649
|
-
if (polyface instanceof
|
|
250810
|
+
if (polyface instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface) {
|
|
250650
250811
|
return this.collectRangeLengthData(polyface.createVisitor(0));
|
|
250651
250812
|
}
|
|
250652
250813
|
const rangeData = new _RangeLengthData__WEBPACK_IMPORTED_MODULE_25__.RangeLengthData();
|
|
@@ -250664,10 +250825,10 @@ class PolyfaceQuery {
|
|
|
250664
250825
|
const rangeSearcher = _multiclip_XYPointBuckets__WEBPACK_IMPORTED_MODULE_26__.XYPointBuckets.create(polyface.data.point, 30);
|
|
250665
250826
|
const builder = _PolyfaceBuilder__WEBPACK_IMPORTED_MODULE_16__.PolyfaceBuilder.create();
|
|
250666
250827
|
const edgeRange = _geometry3d_Range__WEBPACK_IMPORTED_MODULE_27__.Range3d.createNull();
|
|
250667
|
-
const point0 =
|
|
250668
|
-
const point1 =
|
|
250669
|
-
const spacePoint =
|
|
250670
|
-
const segment =
|
|
250828
|
+
const point0 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
|
|
250829
|
+
const point1 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
|
|
250830
|
+
const spacePoint = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
|
|
250831
|
+
const segment = _curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_11__.LineSegment3d.create(point0, point1);
|
|
250671
250832
|
for (oldFacetVisitor.reset(); oldFacetVisitor.moveToNextFacet();) {
|
|
250672
250833
|
newFacetVisitor.clearArrays();
|
|
250673
250834
|
for (let i = 0; i + 1 < oldFacetVisitor.point.length; i++) {
|
|
@@ -250676,7 +250837,7 @@ class PolyfaceQuery {
|
|
|
250676
250837
|
oldFacetVisitor.point.getPoint3dAtUncheckedPointIndex(i + 1, point1);
|
|
250677
250838
|
newFacetVisitor.pushDataFrom(oldFacetVisitor, i);
|
|
250678
250839
|
edgeRange.setNull();
|
|
250679
|
-
|
|
250840
|
+
_curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_11__.LineSegment3d.create(point0, point1, segment);
|
|
250680
250841
|
let detailArray;
|
|
250681
250842
|
edgeRange.extend(point0);
|
|
250682
250843
|
edgeRange.extend(point1);
|
|
@@ -250821,8 +250982,8 @@ class PolyfaceQuery {
|
|
|
250821
250982
|
const oldFacetVisitor = polyface.createVisitor(2); // This is to visit the existing facets.
|
|
250822
250983
|
const newFacetVisitor = polyface.createVisitor(0); // This is to build the new facets.
|
|
250823
250984
|
const builder = _PolyfaceBuilder__WEBPACK_IMPORTED_MODULE_16__.PolyfaceBuilder.create();
|
|
250824
|
-
const vector01 =
|
|
250825
|
-
const vector12 =
|
|
250985
|
+
const vector01 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Vector3d.create();
|
|
250986
|
+
const vector12 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Vector3d.create();
|
|
250826
250987
|
const numPoint = polyface.data.point.length;
|
|
250827
250988
|
const pointState = new Int32Array(numPoint);
|
|
250828
250989
|
// FIRST PASS -- in each sector of each facet, determine if the sector has colinear incoming and outgoing vectors.
|
|
@@ -250869,7 +251030,7 @@ class PolyfaceQuery {
|
|
|
250869
251030
|
*/
|
|
250870
251031
|
static setEdgeVisibility(polyface, clusters, value) {
|
|
250871
251032
|
for (const cluster of clusters) {
|
|
250872
|
-
if (cluster instanceof
|
|
251033
|
+
if (cluster instanceof _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_10__.SortableEdge) {
|
|
250873
251034
|
this.setSingleEdgeVisibility(polyface, cluster.facetIndex, cluster.vertexIndexA, value);
|
|
250874
251035
|
}
|
|
250875
251036
|
else if (Array.isArray(cluster)) {
|
|
@@ -250912,9 +251073,9 @@ class PolyfaceQuery {
|
|
|
250912
251073
|
* @param polyface a mesh, or a visitor assumed to have numWrap === 1
|
|
250913
251074
|
*/
|
|
250914
251075
|
static createIndexedEdges(polyface) {
|
|
250915
|
-
if (polyface instanceof
|
|
251076
|
+
if (polyface instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface)
|
|
250916
251077
|
return this.createIndexedEdges(polyface.createVisitor(1));
|
|
250917
|
-
const edges = new
|
|
251078
|
+
const edges = new _IndexedEdgeMatcher__WEBPACK_IMPORTED_MODULE_10__.IndexedEdgeMatcher();
|
|
250918
251079
|
polyface.reset();
|
|
250919
251080
|
while (polyface.moveToNextFacet()) {
|
|
250920
251081
|
const numEdges = polyface.pointCount - 1;
|
|
@@ -250933,17 +251094,17 @@ class PolyfaceQuery {
|
|
|
250933
251094
|
* @param sharpEdges true to reverse the angle threshold test and return sharp edges; otherwise return smooth edges (default)
|
|
250934
251095
|
*/
|
|
250935
251096
|
static collectEdgesByDihedralAngle(mesh, maxSmoothEdgeAngle, sharpEdges = false) {
|
|
250936
|
-
if (mesh instanceof
|
|
251097
|
+
if (mesh instanceof _Polyface__WEBPACK_IMPORTED_MODULE_4__.Polyface)
|
|
250937
251098
|
return this.collectEdgesByDihedralAngle(mesh.createVisitor(1), maxSmoothEdgeAngle, sharpEdges);
|
|
250938
251099
|
mesh.setNumWrap(1);
|
|
250939
251100
|
const allEdges = this.createIndexedEdges(mesh);
|
|
250940
251101
|
const manifoldEdges = [];
|
|
250941
251102
|
allEdges.sortAndCollectClusters(manifoldEdges);
|
|
250942
251103
|
if (undefined === maxSmoothEdgeAngle || maxSmoothEdgeAngle.radians < 0)
|
|
250943
|
-
maxSmoothEdgeAngle =
|
|
251104
|
+
maxSmoothEdgeAngle = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_0__.Angle.createRadians(_Geometry__WEBPACK_IMPORTED_MODULE_6__.Geometry.smallAngleRadians);
|
|
250944
251105
|
const outEdges = [];
|
|
250945
|
-
const normal0 =
|
|
250946
|
-
const normal1 =
|
|
251106
|
+
const normal0 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Vector3d.create();
|
|
251107
|
+
const normal1 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Vector3d.create();
|
|
250947
251108
|
for (const pair of manifoldEdges) {
|
|
250948
251109
|
if (Array.isArray(pair) && pair.length === 2) {
|
|
250949
251110
|
const e0 = pair[0];
|
|
@@ -250982,8 +251143,8 @@ class PolyfaceQuery {
|
|
|
250982
251143
|
this.markAllEdgeVisibility(mesh, false);
|
|
250983
251144
|
this.setEdgeVisibility(mesh, boundaryEdges, true);
|
|
250984
251145
|
if (sharpEdgeAngle !== undefined) {
|
|
250985
|
-
const normal0 =
|
|
250986
|
-
const normal1 =
|
|
251146
|
+
const normal0 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Vector3d.create();
|
|
251147
|
+
const normal1 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Vector3d.create();
|
|
250987
251148
|
for (const pair of pairedEdges) {
|
|
250988
251149
|
if (Array.isArray(pair) && pair.length === 2) {
|
|
250989
251150
|
const e0 = pair[0];
|
|
@@ -251005,9 +251166,9 @@ class PolyfaceQuery {
|
|
|
251005
251166
|
*/
|
|
251006
251167
|
static computeFacetUnitNormal(visitor, facetIndex, result) {
|
|
251007
251168
|
if (!result)
|
|
251008
|
-
result =
|
|
251169
|
+
result = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Vector3d.create();
|
|
251009
251170
|
if (visitor.moveToReadIndex(facetIndex)) {
|
|
251010
|
-
if (
|
|
251171
|
+
if (_geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_5__.PolygonOps.unitNormal(visitor.point, result))
|
|
251011
251172
|
return result;
|
|
251012
251173
|
}
|
|
251013
251174
|
return undefined;
|
|
@@ -251022,20 +251183,41 @@ class PolyfaceQuery {
|
|
|
251022
251183
|
for (let i = 0; i < data.edgeVisible.length; i++)
|
|
251023
251184
|
data.edgeVisible[i] = value;
|
|
251024
251185
|
}
|
|
251186
|
+
/**
|
|
251187
|
+
* Create a HalfEdgeGraph with a face for each facet of the IndexedPolyface
|
|
251188
|
+
* @param mesh mesh to convert
|
|
251189
|
+
* @internal
|
|
251190
|
+
*/
|
|
251191
|
+
static convertToHalfEdgeGraph(mesh) {
|
|
251192
|
+
const builder = new _topology_HalfEdgeGraphFromIndexedLoopsContext__WEBPACK_IMPORTED_MODULE_28__.HalfEdgeGraphFromIndexedLoopsContext();
|
|
251193
|
+
const visitor = mesh.createVisitor(0);
|
|
251194
|
+
for (visitor.reset(); visitor.moveToNextFacet();) {
|
|
251195
|
+
builder.insertLoop(visitor.pointIndex);
|
|
251196
|
+
}
|
|
251197
|
+
const graph = builder.graph;
|
|
251198
|
+
const xyz = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_7__.Point3d.create();
|
|
251199
|
+
graph.announceNodes((_graph, halfEdge) => {
|
|
251200
|
+
const vertexIndex = halfEdge.i;
|
|
251201
|
+
mesh.data.getPoint(vertexIndex, xyz);
|
|
251202
|
+
halfEdge.setXYZ(xyz);
|
|
251203
|
+
return true;
|
|
251204
|
+
});
|
|
251205
|
+
return graph;
|
|
251206
|
+
}
|
|
251025
251207
|
/**
|
|
251026
251208
|
* * Examine adjacent facet orientations throughout the mesh
|
|
251027
251209
|
* * If possible, reverse a subset to achieve proper pairing.
|
|
251028
251210
|
* @param mesh
|
|
251029
251211
|
*/
|
|
251030
251212
|
static reorientVertexOrderAroundFacetsForConsistentOrientation(mesh) {
|
|
251031
|
-
return
|
|
251213
|
+
return _FacetOrientation__WEBPACK_IMPORTED_MODULE_29__.FacetOrientationFixup.doFixup(mesh);
|
|
251032
251214
|
}
|
|
251033
251215
|
/**
|
|
251034
251216
|
* Set up indexed normals with one normal in the plane of each facet of the mesh.
|
|
251035
251217
|
* @param polyface
|
|
251036
251218
|
*/
|
|
251037
251219
|
static buildPerFaceNormals(polyface) {
|
|
251038
|
-
|
|
251220
|
+
_multiclip_BuildAverageNormalsContext__WEBPACK_IMPORTED_MODULE_30__.BuildAverageNormalsContext.buildPerFaceNormals(polyface);
|
|
251039
251221
|
}
|
|
251040
251222
|
/**
|
|
251041
251223
|
* * At each vertex of the mesh
|
|
@@ -251047,8 +251229,21 @@ class PolyfaceQuery {
|
|
|
251047
251229
|
* @param polyface polyface to update.
|
|
251048
251230
|
* @param toleranceAngle averaging is done between normals up to this angle.
|
|
251049
251231
|
*/
|
|
251050
|
-
static buildAverageNormals(polyface, toleranceAngle =
|
|
251051
|
-
|
|
251232
|
+
static buildAverageNormals(polyface, toleranceAngle = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_0__.Angle.createDegrees(31.0)) {
|
|
251233
|
+
_multiclip_BuildAverageNormalsContext__WEBPACK_IMPORTED_MODULE_30__.BuildAverageNormalsContext.buildFastAverageNormals(polyface, toleranceAngle);
|
|
251234
|
+
}
|
|
251235
|
+
/**
|
|
251236
|
+
* Offset the faces of the mesh.
|
|
251237
|
+
* @param source original mesh
|
|
251238
|
+
* @param signedOffsetDistance distance to offset
|
|
251239
|
+
* @param offsetOptions angle options. The default options are recommended.
|
|
251240
|
+
* @returns shifted mesh.
|
|
251241
|
+
*/
|
|
251242
|
+
static cloneOffset(source, signedOffsetDistance, offsetOptions = OffsetMeshOptions.create()) {
|
|
251243
|
+
const strokeOptions = _curve_StrokeOptions__WEBPACK_IMPORTED_MODULE_23__.StrokeOptions.createForFacets();
|
|
251244
|
+
const offsetBuilder = _PolyfaceBuilder__WEBPACK_IMPORTED_MODULE_16__.PolyfaceBuilder.create(strokeOptions);
|
|
251245
|
+
_multiclip_OffsetMeshContext__WEBPACK_IMPORTED_MODULE_31__.OffsetMeshContext.buildOffsetMeshWithEdgeChamfers(source, offsetBuilder, signedOffsetDistance, offsetOptions);
|
|
251246
|
+
return offsetBuilder.claimPolyface();
|
|
251052
251247
|
}
|
|
251053
251248
|
}
|
|
251054
251249
|
// amount of computation to do per step of async methods.
|
|
@@ -251960,6 +252155,1064 @@ class LinearSearchRange2dArray {
|
|
|
251960
252155
|
}
|
|
251961
252156
|
|
|
251962
252157
|
|
|
252158
|
+
/***/ }),
|
|
252159
|
+
|
|
252160
|
+
/***/ "../../core/geometry/lib/esm/polyface/multiclip/OffsetMeshContext.js":
|
|
252161
|
+
/*!***************************************************************************!*\
|
|
252162
|
+
!*** ../../core/geometry/lib/esm/polyface/multiclip/OffsetMeshContext.js ***!
|
|
252163
|
+
\***************************************************************************/
|
|
252164
|
+
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
252165
|
+
|
|
252166
|
+
"use strict";
|
|
252167
|
+
__webpack_require__.r(__webpack_exports__);
|
|
252168
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
252169
|
+
/* harmony export */ "FacetOffsetProperties": () => (/* binding */ FacetOffsetProperties),
|
|
252170
|
+
/* harmony export */ "OffsetMeshContext": () => (/* binding */ OffsetMeshContext),
|
|
252171
|
+
/* harmony export */ "SectorOffsetProperties": () => (/* binding */ SectorOffsetProperties)
|
|
252172
|
+
/* harmony export */ });
|
|
252173
|
+
/* harmony import */ var _numerics_Polynomials__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../numerics/Polynomials */ "../../core/geometry/lib/esm/numerics/Polynomials.js");
|
|
252174
|
+
/* harmony import */ var _geometry3d_GrowableXYZArray__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../geometry3d/GrowableXYZArray */ "../../core/geometry/lib/esm/geometry3d/GrowableXYZArray.js");
|
|
252175
|
+
/* harmony import */ var _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../geometry3d/Point3dVector3d */ "../../core/geometry/lib/esm/geometry3d/Point3dVector3d.js");
|
|
252176
|
+
/* harmony import */ var _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../geometry3d/PolygonOps */ "../../core/geometry/lib/esm/geometry3d/PolygonOps.js");
|
|
252177
|
+
/* harmony import */ var _geometry3d_Ray3d__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../../geometry3d/Ray3d */ "../../core/geometry/lib/esm/geometry3d/Ray3d.js");
|
|
252178
|
+
/* harmony import */ var _topology_Graph__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../topology/Graph */ "../../core/geometry/lib/esm/topology/Graph.js");
|
|
252179
|
+
/* harmony import */ var _topology_HalfEdgeGraphFromIndexedLoopsContext__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../topology/HalfEdgeGraphFromIndexedLoopsContext */ "../../core/geometry/lib/esm/topology/HalfEdgeGraphFromIndexedLoopsContext.js");
|
|
252180
|
+
/* harmony import */ var _Geometry__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../Geometry */ "../../core/geometry/lib/esm/Geometry.js");
|
|
252181
|
+
/* harmony import */ var _geometry3d_PolylineCompressionByEdgeOffset__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../geometry3d/PolylineCompressionByEdgeOffset */ "../../core/geometry/lib/esm/geometry3d/PolylineCompressionByEdgeOffset.js");
|
|
252182
|
+
/* harmony import */ var _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../../geometry3d/Angle */ "../../core/geometry/lib/esm/geometry3d/Angle.js");
|
|
252183
|
+
/*---------------------------------------------------------------------------------------------
|
|
252184
|
+
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
252185
|
+
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
252186
|
+
*--------------------------------------------------------------------------------------------*/
|
|
252187
|
+
/** @packageDocumentation
|
|
252188
|
+
* @module Polyface
|
|
252189
|
+
*/
|
|
252190
|
+
|
|
252191
|
+
|
|
252192
|
+
|
|
252193
|
+
|
|
252194
|
+
|
|
252195
|
+
|
|
252196
|
+
|
|
252197
|
+
|
|
252198
|
+
|
|
252199
|
+
|
|
252200
|
+
function isDefinedAndTrue(value) {
|
|
252201
|
+
if (value === undefined)
|
|
252202
|
+
return false;
|
|
252203
|
+
return value;
|
|
252204
|
+
}
|
|
252205
|
+
class AverageNormalData {
|
|
252206
|
+
constructor() {
|
|
252207
|
+
this.numActiveSectors = 0;
|
|
252208
|
+
this.numInactiveSectors = 0; // exterior and sling.
|
|
252209
|
+
this.averageNormal = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Vector3d.create();
|
|
252210
|
+
this.radiansSum = 0.0;
|
|
252211
|
+
this.maxDeviationRadiansFromAverage = 0.0;
|
|
252212
|
+
}
|
|
252213
|
+
clear() {
|
|
252214
|
+
this.numActiveSectors = 0;
|
|
252215
|
+
this.numInactiveSectors = 0; // exterior and sling.
|
|
252216
|
+
this.averageNormal.setZero();
|
|
252217
|
+
this.radiansSum = 0.0;
|
|
252218
|
+
this.maxDeviationRadiansFromAverage = 0.0;
|
|
252219
|
+
}
|
|
252220
|
+
/** Add a normal to the evolving sum, scaled by radians in the corner */
|
|
252221
|
+
accumulateNormal(node, normal, inactiveMask) {
|
|
252222
|
+
if (node.isMaskSet(inactiveMask)) {
|
|
252223
|
+
this.numInactiveSectors++;
|
|
252224
|
+
}
|
|
252225
|
+
else {
|
|
252226
|
+
const sectorSweepRadians = _topology_Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdge.sectorSweepRadiansXYZ(node, normal);
|
|
252227
|
+
this.averageNormal.addScaledInPlace(normal, sectorSweepRadians);
|
|
252228
|
+
this.radiansSum += sectorSweepRadians;
|
|
252229
|
+
this.numActiveSectors++;
|
|
252230
|
+
}
|
|
252231
|
+
}
|
|
252232
|
+
/** normalize the accumulated normals. */
|
|
252233
|
+
finishNormalAveraging() {
|
|
252234
|
+
if (this.numActiveSectors > 0 && this.averageNormal.normalizeInPlace()) {
|
|
252235
|
+
return true;
|
|
252236
|
+
}
|
|
252237
|
+
return false;
|
|
252238
|
+
}
|
|
252239
|
+
/** Compute the deviation from average. update max deviation member */
|
|
252240
|
+
recordDeviation(normal, isActive) {
|
|
252241
|
+
if (isActive) {
|
|
252242
|
+
const radians = this.averageNormal.radiansTo(normal);
|
|
252243
|
+
this.maxDeviationRadiansFromAverage = Math.max(Math.abs(this.maxDeviationRadiansFromAverage), radians);
|
|
252244
|
+
}
|
|
252245
|
+
else {
|
|
252246
|
+
}
|
|
252247
|
+
}
|
|
252248
|
+
/** Return the max deviation as computed on prior calls to recordDeviation */
|
|
252249
|
+
get maxDeviationRadians() { return this.maxDeviationRadiansFromAverage; }
|
|
252250
|
+
}
|
|
252251
|
+
function emitSector(sector) {
|
|
252252
|
+
if (OffsetMeshContext.stringDebugFunction !== undefined) {
|
|
252253
|
+
OffsetMeshContext.stringDebugFunction(` Sector xyz ${sector.xyz.x},${sector.xyz.y},${sector.xyz.z} `);
|
|
252254
|
+
OffsetMeshContext.stringDebugFunction(` normal ${sector.normal.x},${sector.normal.y},${sector.normal.z} `);
|
|
252255
|
+
}
|
|
252256
|
+
}
|
|
252257
|
+
// facet properties used during offset.
|
|
252258
|
+
//
|
|
252259
|
+
class FacetOffsetProperties {
|
|
252260
|
+
constructor(facetIndex, normal) {
|
|
252261
|
+
this.facetIndex = facetIndex;
|
|
252262
|
+
this.facetNormal = normal;
|
|
252263
|
+
}
|
|
252264
|
+
}
|
|
252265
|
+
/**
|
|
252266
|
+
* Sector properties during offset.
|
|
252267
|
+
* * this.normal may be initially assigned as the facet normal but can mutate by
|
|
252268
|
+
* averaging with neighbors.
|
|
252269
|
+
* * this.xyz is initially the base mesh xyz but is expected to move along the normal.
|
|
252270
|
+
* * this.count is used locally in computations.
|
|
252271
|
+
*/
|
|
252272
|
+
class SectorOffsetProperties {
|
|
252273
|
+
constructor(normal, xyz) {
|
|
252274
|
+
this.xyz = xyz;
|
|
252275
|
+
this.normal = normal;
|
|
252276
|
+
this.count = 0;
|
|
252277
|
+
}
|
|
252278
|
+
/**
|
|
252279
|
+
* Compute the angle between plane normals on opposite sides of the edge.
|
|
252280
|
+
* * parallel normals have zero angle.
|
|
252281
|
+
* * if the edge cuts inward to the volume behind the faces, the angle is negative.
|
|
252282
|
+
* * if the edge is outward (a convex edge) the the volume, the angle is positive.
|
|
252283
|
+
* @param edgeNodeA node on one side of the edge
|
|
252284
|
+
* @param edgeVector pre-allocated vector to receive vector along edge.
|
|
252285
|
+
* @param averageNormal pre-allocated vector to receive the average normal for a chamfer of the offset edge.
|
|
252286
|
+
* @param offsetDistance distance of offset being constructed. The sign of this resolves angle ambiguity.
|
|
252287
|
+
* @param radiansTolerance tolerance for large angle between normals.
|
|
252288
|
+
* @returns true if this edge has SectorOffsetProperties on both sides and the angle between normals angle exceeds radiansTolerance.
|
|
252289
|
+
*/
|
|
252290
|
+
static edgeHasLargeExteriorAngleBetweenNormals(edgeNodeA, edgeVector, averageNormal, offsetDistance, radiansTolerance = Math.PI * 0.5) {
|
|
252291
|
+
const propsA = edgeNodeA.edgeTag;
|
|
252292
|
+
const edgeNodeB = edgeNodeA.edgeMate;
|
|
252293
|
+
const propsB = edgeNodeB.edgeTag;
|
|
252294
|
+
if (propsA !== undefined && propsB !== undefined) {
|
|
252295
|
+
edgeNodeA.vectorToFaceSuccessor(edgeVector);
|
|
252296
|
+
const radians = propsA.normal.signedRadiansTo(propsB.normal, edgeVector);
|
|
252297
|
+
if (_Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.split3WaySign(offsetDistance, -1, 1, 1) * radians >= radiansTolerance) {
|
|
252298
|
+
_geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Vector3d.createAdd2Scaled(propsA.normal, 1.0, propsB.normal, 1.0, averageNormal);
|
|
252299
|
+
if (averageNormal.normalizeInPlace())
|
|
252300
|
+
return true;
|
|
252301
|
+
}
|
|
252302
|
+
}
|
|
252303
|
+
return false;
|
|
252304
|
+
}
|
|
252305
|
+
static almostEqualNormals(sectorA, sectorB, radiansTolerance = _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.smallAngleRadians) {
|
|
252306
|
+
return sectorA.normal.radiansTo(sectorB.normal) <= radiansTolerance;
|
|
252307
|
+
}
|
|
252308
|
+
static radiansBetweenNormals(sectorA, sectorB) {
|
|
252309
|
+
return sectorA.normal.radiansTo(sectorB.normal);
|
|
252310
|
+
}
|
|
252311
|
+
// Set the offset point this.xyz as sum of the nodeXyz + distance * this.normal
|
|
252312
|
+
setOffsetPointAtDistanceAtHalfEdge(halfEdge, distance) {
|
|
252313
|
+
halfEdge.getPoint3d(this.xyz);
|
|
252314
|
+
this.xyz.addScaledInPlace(this.normal, distance);
|
|
252315
|
+
}
|
|
252316
|
+
// Copy xyz from parameter into (preexisting object) xyz
|
|
252317
|
+
static setXYZAtHalfEdge(halfEdge, xyz) {
|
|
252318
|
+
const props = halfEdge.edgeTag;
|
|
252319
|
+
if (props !== undefined && xyz !== undefined)
|
|
252320
|
+
props.xyz.set(xyz.x, xyz.y, xyz.z);
|
|
252321
|
+
}
|
|
252322
|
+
// Set the offset point this.xyz directly
|
|
252323
|
+
setXYAndZ(xyz) {
|
|
252324
|
+
this.xyz.set(xyz.x, xyz.y, xyz.z);
|
|
252325
|
+
}
|
|
252326
|
+
// Look through the half edge to its properties. Set the normal there. Optionally set xyz from node xyz and offset distance
|
|
252327
|
+
static setNormalAtHalfEdge(halfEdge, uvw, distance) {
|
|
252328
|
+
const props = halfEdge.edgeTag;
|
|
252329
|
+
if (props !== undefined) {
|
|
252330
|
+
props.normal.set(uvw.x, uvw.y, uvw.z);
|
|
252331
|
+
if (distance !== undefined)
|
|
252332
|
+
props.setOffsetPointAtDistanceAtHalfEdge(halfEdge, distance);
|
|
252333
|
+
}
|
|
252334
|
+
}
|
|
252335
|
+
// Look through the half edge and its vertex successor to properties. Get the two normals. Return the angle sweeping from one to the next
|
|
252336
|
+
static sweepRadiansAroundNormal(nodeA, upVector) {
|
|
252337
|
+
const propsA = nodeA.edgeTag;
|
|
252338
|
+
const propsB = nodeA.vertexSuccessor.edgeTag;
|
|
252339
|
+
if (propsA !== undefined && propsB !== undefined) {
|
|
252340
|
+
return propsA.normal.planarRadiansTo(propsB.normal, upVector);
|
|
252341
|
+
}
|
|
252342
|
+
return undefined;
|
|
252343
|
+
}
|
|
252344
|
+
// Look through the half edge to its properties. return (if possible) the coordinates
|
|
252345
|
+
static getSectorPointAtHalfEdge(halfEdge, xyz, xyzArray) {
|
|
252346
|
+
const props = halfEdge.edgeTag;
|
|
252347
|
+
if (props !== undefined) {
|
|
252348
|
+
if (xyz !== undefined)
|
|
252349
|
+
xyz.setFromPoint3d(props.xyz);
|
|
252350
|
+
if (xyzArray !== undefined)
|
|
252351
|
+
xyzArray.push(props.xyz);
|
|
252352
|
+
return true;
|
|
252353
|
+
}
|
|
252354
|
+
return false;
|
|
252355
|
+
}
|
|
252356
|
+
// access the XYZ and push to the array (which makes copies, not reference)
|
|
252357
|
+
// return pointer to the SectorOffsetProperties
|
|
252358
|
+
static pushXYZ(xyzArray, halfEdge) {
|
|
252359
|
+
const sector = halfEdge.edgeTag;
|
|
252360
|
+
if (sector !== undefined)
|
|
252361
|
+
xyzArray.push(sector.xyz);
|
|
252362
|
+
return sector;
|
|
252363
|
+
}
|
|
252364
|
+
// Dereference to execute: accumulatingVector += halfEdge.edgeTag.normal * scale
|
|
252365
|
+
static accumulateScaledNormalAtHalfEdge(halfEdge, scale, accumulatingVector) {
|
|
252366
|
+
const sector = halfEdge.edgeTag;
|
|
252367
|
+
if (sector !== undefined)
|
|
252368
|
+
accumulatingVector.addScaledInPlace(sector.normal, scale);
|
|
252369
|
+
}
|
|
252370
|
+
}
|
|
252371
|
+
/*
|
|
252372
|
+
About Chamfer Edges ..... as constructed in addChamferTopologyToAllEdges
|
|
252373
|
+
|
|
252374
|
+
When edge vertex X to vertex Y has a sharp angle between normals, a "chamfer face" must be created to "fatten" it.
|
|
252375
|
+
|
|
252376
|
+
The original half edges (nodes) for the edge are AX and AY. These are "mates" in the halfEdge mental model. As always,
|
|
252377
|
+
AX is (as needed)
|
|
252378
|
+
(i) the preferred half edge for the left side of the edge moving from X to Y. (i.e. above the edge)
|
|
252379
|
+
(ii) a part of the face loop for the face to the left when proceeding CCW around the face to the above the drawn edge
|
|
252380
|
+
(iii) a part of the vertex loop around X
|
|
252381
|
+
Likewise, AY is (as needed)
|
|
252382
|
+
(i) the preferred half edge for the left side of the edge moving from Y to X (i.e. below the edge)
|
|
252383
|
+
(ii) a part of the face loop for the face to the left of the edge when proceeding CCW around the face below the edge.
|
|
252384
|
+
(iii) a part of the vertex loop around Y
|
|
252385
|
+
|
|
252386
|
+
AX------>
|
|
252387
|
+
X______________________________________________________________________Y
|
|
252388
|
+
<---AY
|
|
252389
|
+
|
|
252390
|
+
When the chamfer face is created, it needs to have a sliver face "inside the edge" -- something in the space here
|
|
252391
|
+
|
|
252392
|
+
AX------>
|
|
252393
|
+
_____________________________________________________________________
|
|
252394
|
+
/ \
|
|
252395
|
+
X Y
|
|
252396
|
+
\_____________________________________________________________________/
|
|
252397
|
+
<---AY
|
|
252398
|
+
|
|
252399
|
+
The chamfer face will have a plane normal is the average of the two faces' plane normals.
|
|
252400
|
+
|
|
252401
|
+
The creation sequence for the chamfer face puts a slit "inside the edge" as above HalfEdges AX and AY remain as parts
|
|
252402
|
+
of their respective face loops. In addition, at each end a singleton edge "sling" face is inserted at each
|
|
252403
|
+
end of the sliver face.
|
|
252404
|
+
|
|
252405
|
+
The sequence is:
|
|
252406
|
+
|
|
252407
|
+
STEP 1: splitEdgeCreateSliver creates the sliver face with 2 half edges DX and DY
|
|
252408
|
+
STEP 2: splitEdge (with undefined as the "prior" edge) creates a sling with HalfEdge CX "inside" and BX "outside".
|
|
252409
|
+
(The sling face is not yet attached to X -- briefly floating in space)
|
|
252410
|
+
STEP 3: pinch of HalfEdges BX and DX inserts the sling face "inside" the slit face at the X end.
|
|
252411
|
+
|
|
252412
|
+
Steps 2 and 3 are executed from each end. Due to the symmetric structure, a 2-pass loop can apply the logic at each end without distinct names in code.
|
|
252413
|
+
|
|
252414
|
+
AX------>
|
|
252415
|
+
_______________________________________________________________
|
|
252416
|
+
/ <---DY \
|
|
252417
|
+
/ \
|
|
252418
|
+
/ BX---> \
|
|
252419
|
+
/ _______________ _______________ \
|
|
252420
|
+
| / \ / <----CY \ |
|
|
252421
|
+
|/ \ / \|
|
|
252422
|
+
X | | Y
|
|
252423
|
+
|\ CX---> / \ /|
|
|
252424
|
+
| \_______________/ \_______________/ |
|
|
252425
|
+
\ <---BY /
|
|
252426
|
+
\ /
|
|
252427
|
+
\ DX---> /
|
|
252428
|
+
\ ______________________________________________________________/
|
|
252429
|
+
<---AY
|
|
252430
|
+
|
|
252431
|
+
During the construction, the letters ABCD are used as above, but with prefixes emphasizing their role
|
|
252432
|
+
outsideAX, outsideAY
|
|
252433
|
+
slingB, slingC, sliverD
|
|
252434
|
+
|
|
252435
|
+
The "inside" sling faces (CX and CY) each have their own FacetOffsetProperties and SectorOffsetProperties.
|
|
252436
|
+
The sliver face has its own FacetOffsetProperties which are referenced by DX, BY, DY, BX.
|
|
252437
|
+
Each of those 4 has its own SectorOffSetProperties.
|
|
252438
|
+
|
|
252439
|
+
Important properties during offset construction:
|
|
252440
|
+
1) the original graph always has original topology and coordinates
|
|
252441
|
+
2) Each face of the original graph has a FacetOffsetProperties with a representative point and a normal. These are unchanged during the computation.
|
|
252442
|
+
3) Each node has its own SectorOffsetProperties with a coordinate and normal independent of the parent node.
|
|
252443
|
+
3.1 The first offset coordinates in each node are directly offset by face normal.
|
|
252444
|
+
3.2 This creates mismatch across edges and around vertices.
|
|
252445
|
+
3.3 Various sweeps "around each vertex" try to do intersections among appropriate offset planes to find
|
|
252446
|
+
common coordinates in place of the initial mismatches.
|
|
252447
|
+
4) The independence of all the sectors allows the offset construction to fix things up in any order it chooses.
|
|
252448
|
+
5) During the construction, the xyz in SectorOffsetProperties around a single vertex do NOT have to match.
|
|
252449
|
+
6) At output time, there are three sweeps:
|
|
252450
|
+
6.1: By face: Go around the face and output a facet with the coordinates in the various sectors.
|
|
252451
|
+
6.2: By edge: For each edge, if the sector xyz match across both ends output nothing. If not, output a triangle or quad
|
|
252452
|
+
6.3: By vertex: At each vertex, if all vertex coordinates match output nothing. Otherwise output a facet with all the coordinates.
|
|
252453
|
+
*/
|
|
252454
|
+
class OffsetMeshContext {
|
|
252455
|
+
constructor(basePolyface, baseGraph, options) {
|
|
252456
|
+
this._basePolyface = basePolyface;
|
|
252457
|
+
this._baseGraph = baseGraph;
|
|
252458
|
+
this._breakMaskA = baseGraph.grabMask();
|
|
252459
|
+
this._breakMaskB = baseGraph.grabMask();
|
|
252460
|
+
this._insideOfChamferFace = baseGraph.grabMask();
|
|
252461
|
+
this._outsideOfChamferFace = baseGraph.grabMask();
|
|
252462
|
+
this._insideChamferSling = baseGraph.grabMask();
|
|
252463
|
+
this._outsideEndOfChamferFace = baseGraph.grabMask();
|
|
252464
|
+
this._exteriorMask = _topology_Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdgeMask.EXTERIOR;
|
|
252465
|
+
this._offsetCoordinatesReassigned = baseGraph.grabMask();
|
|
252466
|
+
this._smoothRadiansBetweenNormals = options.smoothSingleAngleBetweenNormals.radians;
|
|
252467
|
+
this._chamferTurnRadians = options.chamferAngleBetweenNormals.radians;
|
|
252468
|
+
this._smoothAccumulatedRadiansBetweenNormals = options.smoothAccumulatedAngleBetweenNormals.radians;
|
|
252469
|
+
}
|
|
252470
|
+
/** "Exterior" side of a bare edge of the mesh */
|
|
252471
|
+
get exteriorMask() { return this._exteriorMask; }
|
|
252472
|
+
/** "First" sector of a smooth sequence. */
|
|
252473
|
+
get breakMaskA() { return this._breakMaskA; }
|
|
252474
|
+
/** "Last" sector of a smooth sequence. */
|
|
252475
|
+
get breakMaskB() { return this._breakMaskB; }
|
|
252476
|
+
/** This edge is on a chamfered face, and along the original edge */
|
|
252477
|
+
get insideOfChamferFace() { return this._insideOfChamferFace; }
|
|
252478
|
+
/** This is the original edge of a chamfer face */
|
|
252479
|
+
get outsideOfChamferFace() { return this._outsideOfChamferFace; }
|
|
252480
|
+
/** This edge is on a chamfered face, and at the end -- other side may be a sling */
|
|
252481
|
+
get insideChamferSling() { return this._insideChamferSling; }
|
|
252482
|
+
/** This is the outside of the end of a chamfer face -- i.e. the inside of a new face-at-vertex */
|
|
252483
|
+
get outsideEndOfChamferFace() { return this._outsideEndOfChamferFace; }
|
|
252484
|
+
// At each node . .
|
|
252485
|
+
// * Find the sector data
|
|
252486
|
+
// * recompute the sector point using node XYZ and sectorData normal.
|
|
252487
|
+
applyFaceNormalOffsetsToSectorData(distance) {
|
|
252488
|
+
this._baseGraph.announceNodes((_graph, node) => {
|
|
252489
|
+
const sectorData = node.edgeTag;
|
|
252490
|
+
if (sectorData !== undefined) {
|
|
252491
|
+
sectorData.setOffsetPointAtDistanceAtHalfEdge(node, distance);
|
|
252492
|
+
}
|
|
252493
|
+
return true;
|
|
252494
|
+
});
|
|
252495
|
+
}
|
|
252496
|
+
/**
|
|
252497
|
+
* * build a mesh offset by given distance.
|
|
252498
|
+
* * output the mesh to the given builder.
|
|
252499
|
+
* @param basePolyface original mesh
|
|
252500
|
+
* @param builder polyface builder to receive the new mesh.
|
|
252501
|
+
* @param distance signed offset distance.
|
|
252502
|
+
*/
|
|
252503
|
+
static buildOffsetMeshWithEdgeChamfers(basePolyface, builder, distance, options) {
|
|
252504
|
+
const baseGraph = this.buildBaseGraph(basePolyface);
|
|
252505
|
+
if (baseGraph !== undefined) {
|
|
252506
|
+
const offsetBuilder = new OffsetMeshContext(basePolyface, baseGraph, options);
|
|
252507
|
+
offsetBuilder.applyFaceNormalOffsetsToSectorData(distance);
|
|
252508
|
+
if (OffsetMeshContext.graphDebugFunction !== undefined)
|
|
252509
|
+
OffsetMeshContext.graphDebugFunction("BaseGraph", baseGraph, offsetBuilder._breakMaskA, offsetBuilder._breakMaskB);
|
|
252510
|
+
const outputSelector = options.outputSelector ? options.outputSelector : {
|
|
252511
|
+
outputOffsetsFromFaces: true,
|
|
252512
|
+
outputOffsetsFromEdges: true,
|
|
252513
|
+
outputOffsetsFromVertices: true,
|
|
252514
|
+
};
|
|
252515
|
+
if (isDefinedAndTrue(outputSelector.outputOffsetsFromFacesBeforeChamfers))
|
|
252516
|
+
offsetBuilder.announceFacetsWithSectorCoordinatesAroundFaces(builder);
|
|
252517
|
+
offsetBuilder.addChamferTopologyToAllEdges(options, distance);
|
|
252518
|
+
offsetBuilder.computeOffsetFacetIntersections(distance);
|
|
252519
|
+
if (OffsetMeshContext.graphDebugFunction !== undefined)
|
|
252520
|
+
OffsetMeshContext.graphDebugFunction("after computeEdgeChamfers", baseGraph, offsetBuilder._breakMaskA, offsetBuilder._breakMaskB);
|
|
252521
|
+
if (isDefinedAndTrue(outputSelector.outputOffsetsFromFaces))
|
|
252522
|
+
offsetBuilder.announceFacetsWithSectorCoordinatesAroundFaces(builder);
|
|
252523
|
+
if (isDefinedAndTrue(outputSelector.outputOffsetsFromEdges))
|
|
252524
|
+
offsetBuilder.announceFacetsWithSectorCoordinatesAroundEdges(builder);
|
|
252525
|
+
if (isDefinedAndTrue(outputSelector.outputOffsetsFromVertices))
|
|
252526
|
+
offsetBuilder.announceFacetsWithSectorCoordinatesAroundVertices(builder);
|
|
252527
|
+
}
|
|
252528
|
+
}
|
|
252529
|
+
/**
|
|
252530
|
+
* For each face of the graph, shift vertices by offsetDistance and emit to the builder as a facet
|
|
252531
|
+
* @param polyfaceBuilder
|
|
252532
|
+
*/
|
|
252533
|
+
announceSimpleOffsetFromFaces(polyfaceBuilder, offsetDistance) {
|
|
252534
|
+
const xyzLoop = new _geometry3d_GrowableXYZArray__WEBPACK_IMPORTED_MODULE_3__.GrowableXYZArray();
|
|
252535
|
+
const xyz = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Point3d.create(); // reused at each point around each facet.
|
|
252536
|
+
const uvw = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Vector3d.create(); // reused once per facet
|
|
252537
|
+
const announceNodeAroundFace = (node) => {
|
|
252538
|
+
node.getPoint3d(xyz);
|
|
252539
|
+
xyz.addInPlace(uvw);
|
|
252540
|
+
xyzLoop.push(xyz);
|
|
252541
|
+
return 0;
|
|
252542
|
+
};
|
|
252543
|
+
this._baseGraph.announceFaceLoops((_graph, seed) => {
|
|
252544
|
+
if (!seed.isMaskSet(_topology_Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdgeMask.EXTERIOR)) {
|
|
252545
|
+
const facetProperties = seed.faceTag;
|
|
252546
|
+
uvw.setFromVector3d(facetProperties.facetNormal.direction);
|
|
252547
|
+
uvw.scaleInPlace(offsetDistance);
|
|
252548
|
+
xyzLoop.length = 0;
|
|
252549
|
+
seed.sumAroundFace(announceNodeAroundFace);
|
|
252550
|
+
polyfaceBuilder.addPolygonGrowableXYZArray(xyzLoop);
|
|
252551
|
+
}
|
|
252552
|
+
return true;
|
|
252553
|
+
});
|
|
252554
|
+
}
|
|
252555
|
+
/**
|
|
252556
|
+
* For each face of the graph, output the xyz of the sector data
|
|
252557
|
+
* @param polyfaceBuilder
|
|
252558
|
+
*/
|
|
252559
|
+
announceFacetsWithSectorCoordinatesAroundFaces(polyfaceBuilder) {
|
|
252560
|
+
const xyzLoop = new _geometry3d_GrowableXYZArray__WEBPACK_IMPORTED_MODULE_3__.GrowableXYZArray();
|
|
252561
|
+
// For face loop visits .. get the point from the sector data.
|
|
252562
|
+
const announceNodeAroundFace = (node) => {
|
|
252563
|
+
const sectorData = node.edgeTag;
|
|
252564
|
+
if (sectorData !== undefined) {
|
|
252565
|
+
xyzLoop.push(sectorData.xyz);
|
|
252566
|
+
}
|
|
252567
|
+
return 0;
|
|
252568
|
+
};
|
|
252569
|
+
this._baseGraph.announceFaceLoops((_graph, seed) => {
|
|
252570
|
+
if (!seed.isMaskSet(_topology_Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdgeMask.EXTERIOR)) {
|
|
252571
|
+
xyzLoop.length = 0;
|
|
252572
|
+
seed.sumAroundFace(announceNodeAroundFace);
|
|
252573
|
+
if (xyzLoop.length > 2)
|
|
252574
|
+
polyfaceBuilder.addPolygonGrowableXYZArray(xyzLoop);
|
|
252575
|
+
}
|
|
252576
|
+
return true;
|
|
252577
|
+
});
|
|
252578
|
+
}
|
|
252579
|
+
countBits(mask) {
|
|
252580
|
+
let n = 0;
|
|
252581
|
+
let mask1 = mask;
|
|
252582
|
+
while (mask1 !== 0) {
|
|
252583
|
+
if (mask1 & 0x01)
|
|
252584
|
+
n++;
|
|
252585
|
+
mask1 = mask1 >> 1;
|
|
252586
|
+
}
|
|
252587
|
+
return n;
|
|
252588
|
+
}
|
|
252589
|
+
/**
|
|
252590
|
+
* For each edge of the graph . .
|
|
252591
|
+
* * Collect coordinates in 4 sectors going around the edge
|
|
252592
|
+
* * Compress with tight tolerance so adjacent sectors with clean point match reduce to a single point.
|
|
252593
|
+
* * Emit as a facet.
|
|
252594
|
+
* @param polyfaceBuilder
|
|
252595
|
+
*/
|
|
252596
|
+
announceFacetsWithSectorCoordinatesAroundEdges(polyfaceBuilder) {
|
|
252597
|
+
const xyzLoop = new _geometry3d_GrowableXYZArray__WEBPACK_IMPORTED_MODULE_3__.GrowableXYZArray();
|
|
252598
|
+
const primaryCompressionTolerance = _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.smallMetricDistance;
|
|
252599
|
+
const allMasksForEdgesToIgnore = this._exteriorMask
|
|
252600
|
+
| this._outsideEndOfChamferFace
|
|
252601
|
+
| this._outsideOfChamferFace
|
|
252602
|
+
| this._insideOfChamferFace
|
|
252603
|
+
| this._insideChamferSling;
|
|
252604
|
+
this._baseGraph.announceEdges((_graph, nodeA) => {
|
|
252605
|
+
// This starts by looking for EXTERIOR on both sides ...
|
|
252606
|
+
if (nodeA.findMaskAroundEdge(this._exteriorMask) !== undefined) {
|
|
252607
|
+
return true;
|
|
252608
|
+
}
|
|
252609
|
+
else if (!nodeA.isMaskSet(allMasksForEdgesToIgnore)) { // By design, we believe that these two test for allMasksForEdgesToIgnore condition would catch the EXTERIOR case above
|
|
252610
|
+
const nodeB = nodeA.faceSuccessor;
|
|
252611
|
+
const nodeC = nodeA.edgeMate;
|
|
252612
|
+
if (!nodeC.isMaskSet(allMasksForEdgesToIgnore)) {
|
|
252613
|
+
const nodeD = nodeC.faceSuccessor;
|
|
252614
|
+
xyzLoop.clear();
|
|
252615
|
+
SectorOffsetProperties.getSectorPointAtHalfEdge(nodeA, undefined, xyzLoop);
|
|
252616
|
+
SectorOffsetProperties.getSectorPointAtHalfEdge(nodeB, undefined, xyzLoop);
|
|
252617
|
+
SectorOffsetProperties.getSectorPointAtHalfEdge(nodeC, undefined, xyzLoop);
|
|
252618
|
+
SectorOffsetProperties.getSectorPointAtHalfEdge(nodeD, undefined, xyzLoop);
|
|
252619
|
+
_geometry3d_PolylineCompressionByEdgeOffset__WEBPACK_IMPORTED_MODULE_4__.PolylineCompressionContext.compressInPlaceByShortEdgeLength(xyzLoop, primaryCompressionTolerance);
|
|
252620
|
+
if (xyzLoop.length > 2) {
|
|
252621
|
+
polyfaceBuilder.addPolygonGrowableXYZArray(xyzLoop);
|
|
252622
|
+
}
|
|
252623
|
+
}
|
|
252624
|
+
}
|
|
252625
|
+
else {
|
|
252626
|
+
return true;
|
|
252627
|
+
}
|
|
252628
|
+
return true;
|
|
252629
|
+
});
|
|
252630
|
+
}
|
|
252631
|
+
getCoordinateString(node, showXYZ = true, showFaceSuccessorXYZ = false) {
|
|
252632
|
+
if (showXYZ) {
|
|
252633
|
+
if (showFaceSuccessorXYZ) {
|
|
252634
|
+
return `${_topology_Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdge.nodeToIdXYZString(node)} ==> ${_topology_Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdge.nodeToIdXYZString(node.faceSuccessor)}`;
|
|
252635
|
+
}
|
|
252636
|
+
else {
|
|
252637
|
+
return `${_topology_Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdge.nodeToIdXYZString(node)}`;
|
|
252638
|
+
}
|
|
252639
|
+
}
|
|
252640
|
+
else {
|
|
252641
|
+
if (showFaceSuccessorXYZ) {
|
|
252642
|
+
return `==> ${_topology_Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdge.nodeToIdXYZString(node.faceSuccessor)}`;
|
|
252643
|
+
}
|
|
252644
|
+
else {
|
|
252645
|
+
return "";
|
|
252646
|
+
}
|
|
252647
|
+
}
|
|
252648
|
+
}
|
|
252649
|
+
inspectMasks(node, showXYZ = true, showFaceSuccessorXYZ = false) {
|
|
252650
|
+
const s = "[";
|
|
252651
|
+
const v = s.concat(node.id.toString(), node.isMaskSet(this._exteriorMask) ? "X" : "", node.isMaskSet(this.breakMaskA) ? "A" : "", node.isMaskSet(this.breakMaskB) ? "B" : "", node.isMaskSet(this.insideChamferSling) ? "(sling)" : "", node.isMaskSet(this.insideOfChamferFace) ? "(in chamfer)" : "", node.isMaskSet(this.outsideEndOfChamferFace) ? "(@sling)" : "", node.isMaskSet(this.outsideOfChamferFace) ? "(@chamfer)" : "", this.getCoordinateString(node, showXYZ, showFaceSuccessorXYZ), "]");
|
|
252652
|
+
return v;
|
|
252653
|
+
}
|
|
252654
|
+
/**
|
|
252655
|
+
* For each face of the graph, output the xyz of the sector data
|
|
252656
|
+
* @param polyfaceBuilder
|
|
252657
|
+
*/
|
|
252658
|
+
announceFacetsWithSectorCoordinatesAroundVertices(polyfaceBuilder) {
|
|
252659
|
+
const xyzLoop = new _geometry3d_GrowableXYZArray__WEBPACK_IMPORTED_MODULE_3__.GrowableXYZArray();
|
|
252660
|
+
const primaryCompressionTolerance = _Geometry__WEBPACK_IMPORTED_MODULE_2__.Geometry.smallMetricDistance;
|
|
252661
|
+
this._baseGraph.announceVertexLoops((_graph, seed) => {
|
|
252662
|
+
if (!seed.findMaskAroundVertex(this._exteriorMask)) {
|
|
252663
|
+
xyzLoop.length = 0;
|
|
252664
|
+
seed.sumAroundVertex((node) => {
|
|
252665
|
+
if (!node.isMaskSet(this._insideChamferSling))
|
|
252666
|
+
SectorOffsetProperties.getSectorPointAtHalfEdge(node, undefined, xyzLoop);
|
|
252667
|
+
return 0.0;
|
|
252668
|
+
});
|
|
252669
|
+
_geometry3d_PolylineCompressionByEdgeOffset__WEBPACK_IMPORTED_MODULE_4__.PolylineCompressionContext.compressInPlaceByShortEdgeLength(xyzLoop, primaryCompressionTolerance);
|
|
252670
|
+
if (xyzLoop.length > 2) {
|
|
252671
|
+
polyfaceBuilder.addPolygonGrowableXYZArray(xyzLoop);
|
|
252672
|
+
}
|
|
252673
|
+
}
|
|
252674
|
+
return true;
|
|
252675
|
+
});
|
|
252676
|
+
}
|
|
252677
|
+
/**
|
|
252678
|
+
* * Exterior half edges have HalfEdgeMask.EXTERIOR
|
|
252679
|
+
* * All interior half edge around a facet have facetTag pointing to a facetProperties object for that facet.
|
|
252680
|
+
* * the facetOffsetProperties object has the simple facet normal.
|
|
252681
|
+
* * Each half edge has edgeTag pointing to to a sectorOffsetProperties object
|
|
252682
|
+
* * the sectorOffsetProperties has a copy of the facet normal.
|
|
252683
|
+
* @param polyface
|
|
252684
|
+
* @returns graph
|
|
252685
|
+
*/
|
|
252686
|
+
static buildBaseGraph(polyface) {
|
|
252687
|
+
const graphBuilder = new _topology_HalfEdgeGraphFromIndexedLoopsContext__WEBPACK_IMPORTED_MODULE_5__.HalfEdgeGraphFromIndexedLoopsContext();
|
|
252688
|
+
const visitor = polyface.createVisitor();
|
|
252689
|
+
const xyzA = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Point3d.create();
|
|
252690
|
+
const xyzB = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Point3d.create();
|
|
252691
|
+
for (visitor.reset(); visitor.moveToNextFacet();) {
|
|
252692
|
+
const normal = _geometry3d_PolygonOps__WEBPACK_IMPORTED_MODULE_6__.PolygonOps.centroidAreaNormal(visitor.point);
|
|
252693
|
+
if (normal !== undefined) {
|
|
252694
|
+
const edgeA = graphBuilder.insertLoop(visitor.pointIndex, (insideHalfEdge) => {
|
|
252695
|
+
const mate = insideHalfEdge.edgeMate;
|
|
252696
|
+
polyface.data.getPoint(insideHalfEdge.i, xyzA);
|
|
252697
|
+
insideHalfEdge.setXYZ(xyzA);
|
|
252698
|
+
polyface.data.getPoint(mate.i, xyzB);
|
|
252699
|
+
mate.setXYZ(xyzB);
|
|
252700
|
+
});
|
|
252701
|
+
const facetProperties = new FacetOffsetProperties(visitor.currentReadIndex(), normal);
|
|
252702
|
+
if (edgeA !== undefined) {
|
|
252703
|
+
edgeA.sumAroundFace((edgeB) => {
|
|
252704
|
+
edgeB.faceTag = facetProperties;
|
|
252705
|
+
edgeB.edgeTag = new SectorOffsetProperties(normal.direction.clone(), edgeB.getPoint3d());
|
|
252706
|
+
return 0;
|
|
252707
|
+
});
|
|
252708
|
+
}
|
|
252709
|
+
}
|
|
252710
|
+
}
|
|
252711
|
+
return graphBuilder.graph;
|
|
252712
|
+
}
|
|
252713
|
+
setOffsetAtDistanceAroundVertex(vertexSeed, distance, ignoreChamfers = false) {
|
|
252714
|
+
vertexSeed.sumAroundVertex((nodeAroundVertex) => {
|
|
252715
|
+
const props = nodeAroundVertex.edgeTag;
|
|
252716
|
+
if (props !== undefined) {
|
|
252717
|
+
if (ignoreChamfers && this.isInsideChamferOrSling(vertexSeed)) {
|
|
252718
|
+
// SKIP !!
|
|
252719
|
+
}
|
|
252720
|
+
else {
|
|
252721
|
+
props.setOffsetPointAtDistanceAtHalfEdge(nodeAroundVertex, distance);
|
|
252722
|
+
}
|
|
252723
|
+
}
|
|
252724
|
+
return 0.0;
|
|
252725
|
+
});
|
|
252726
|
+
}
|
|
252727
|
+
setOffsetXYAndZAroundVertex(vertexSeed, xyz) {
|
|
252728
|
+
vertexSeed.sumAroundVertex((nodeAroundVertex) => {
|
|
252729
|
+
const props = nodeAroundVertex.edgeTag;
|
|
252730
|
+
if (props !== undefined) {
|
|
252731
|
+
props.setXYAndZ(xyz);
|
|
252732
|
+
nodeAroundVertex.setMask(this._offsetCoordinatesReassigned);
|
|
252733
|
+
}
|
|
252734
|
+
return 0.0;
|
|
252735
|
+
});
|
|
252736
|
+
}
|
|
252737
|
+
/**
|
|
252738
|
+
* * start at vertexSeed.
|
|
252739
|
+
* * set the offset point at up to (and including) one with (a) this._breakMaskB or (b) this._exteriorMask
|
|
252740
|
+
* *
|
|
252741
|
+
* @param vertexSeed first node to mark.
|
|
252742
|
+
* @param f function to call to announce each node and its sector properties.
|
|
252743
|
+
* @returns number of nodes marked.
|
|
252744
|
+
*/
|
|
252745
|
+
announceNodeAndSectorPropertiesInSmoothSector(vertexSeed, f) {
|
|
252746
|
+
let n = 0;
|
|
252747
|
+
for (let currentNode = vertexSeed;; currentNode = currentNode.vertexSuccessor) {
|
|
252748
|
+
const props = currentNode.edgeTag;
|
|
252749
|
+
if (props !== undefined) {
|
|
252750
|
+
f(currentNode, props);
|
|
252751
|
+
n++;
|
|
252752
|
+
}
|
|
252753
|
+
if (currentNode.isMaskSet(this._breakMaskB))
|
|
252754
|
+
return n;
|
|
252755
|
+
// REMARK: these additional exit conditions should not happen if (a) the graph is properly marked and (b) the start node is not exterior.
|
|
252756
|
+
if (currentNode.isMaskSet(this._exteriorMask))
|
|
252757
|
+
return n;
|
|
252758
|
+
if (currentNode === vertexSeed && n === 0)
|
|
252759
|
+
return n;
|
|
252760
|
+
}
|
|
252761
|
+
}
|
|
252762
|
+
computeAverageNormalAndMaxDeviationAroundVertex(vertexSeed, data) {
|
|
252763
|
+
data.clear();
|
|
252764
|
+
const inactiveNodeMask = this._exteriorMask | this._insideChamferSling;
|
|
252765
|
+
vertexSeed.sumAroundVertex((node) => {
|
|
252766
|
+
const sectorData = node.edgeTag;
|
|
252767
|
+
if (sectorData)
|
|
252768
|
+
data.accumulateNormal(node, sectorData.normal, inactiveNodeMask);
|
|
252769
|
+
return 0.0;
|
|
252770
|
+
});
|
|
252771
|
+
if (!data.finishNormalAveraging()) {
|
|
252772
|
+
return undefined;
|
|
252773
|
+
}
|
|
252774
|
+
vertexSeed.sumAroundVertex((node) => {
|
|
252775
|
+
const sectorData = node.edgeTag;
|
|
252776
|
+
if (sectorData)
|
|
252777
|
+
data.recordDeviation(sectorData.normal, !node.isMaskSet(inactiveNodeMask));
|
|
252778
|
+
return 0.0;
|
|
252779
|
+
});
|
|
252780
|
+
return data.maxDeviationRadians;
|
|
252781
|
+
}
|
|
252782
|
+
assignOffsetByAverageNormalAroundVertex(vertexSeed, maxAllowedDeviationRadians, data, distance) {
|
|
252783
|
+
const maxDeviationRadians = this.computeAverageNormalAndMaxDeviationAroundVertex(vertexSeed, data);
|
|
252784
|
+
if (OffsetMeshContext.stringDebugFunction) {
|
|
252785
|
+
OffsetMeshContext.stringDebugFunction(`XYZ ${_topology_Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdge.nodeToIdXYZString(vertexSeed)} Average Normal ${data.averageNormal.toJSON()}`);
|
|
252786
|
+
OffsetMeshContext.stringDebugFunction(` angle ratio ${data.radiansSum / (2 * Math.PI)} maxDeviation ${data.maxDeviationRadiansFromAverage}`);
|
|
252787
|
+
}
|
|
252788
|
+
if (maxDeviationRadians !== undefined && maxDeviationRadians <= maxAllowedDeviationRadians) {
|
|
252789
|
+
vertexSeed.sumAroundVertex((node) => {
|
|
252790
|
+
SectorOffsetProperties.setNormalAtHalfEdge(node, data.averageNormal, distance);
|
|
252791
|
+
return 0;
|
|
252792
|
+
});
|
|
252793
|
+
return true;
|
|
252794
|
+
}
|
|
252795
|
+
return false;
|
|
252796
|
+
}
|
|
252797
|
+
/** Search around a vertex for a sector which has a different normal from its vertexPredecessor.
|
|
252798
|
+
* * The seed will be the first candidate considered
|
|
252799
|
+
*/
|
|
252800
|
+
markBreakEdgesAndSaveAverageNormalsAroundVertex(vertexSeed) {
|
|
252801
|
+
vertexSeed.clearMaskAroundVertex(this._breakMaskA);
|
|
252802
|
+
vertexSeed.clearMaskAroundVertex(this._breakMaskB);
|
|
252803
|
+
const smoothSingleSmoothRadiansBetweenNormals = this._smoothRadiansBetweenNormals;
|
|
252804
|
+
const accumulatedRadiansBetweenNormals = this._smoothAccumulatedRadiansBetweenNormals;
|
|
252805
|
+
// Step 1: Examine the edge between nodeA and the sector on its vertex predecessor side. This (alone) determines single angle breaks.
|
|
252806
|
+
let numBreaks = 0;
|
|
252807
|
+
let nodeP = vertexSeed;
|
|
252808
|
+
let _numSmooth = 0;
|
|
252809
|
+
do {
|
|
252810
|
+
const nodeQ = nodeP.edgeMate;
|
|
252811
|
+
const nodeR = nodeQ.faceSuccessor; // same as nodeA.vertexPredecessor
|
|
252812
|
+
if (nodeP.isMaskSet(this._exteriorMask)) {
|
|
252813
|
+
if (!nodeQ.isMaskSet(this._exteriorMask)) {
|
|
252814
|
+
nodeR.setMask(this._breakMaskB);
|
|
252815
|
+
numBreaks++;
|
|
252816
|
+
}
|
|
252817
|
+
}
|
|
252818
|
+
else {
|
|
252819
|
+
if (nodeP.isMaskSet(this._outsideOfChamferFace)) {
|
|
252820
|
+
nodeP.setMask(this._breakMaskA);
|
|
252821
|
+
}
|
|
252822
|
+
else if (nodeP.isMaskSet(this._outsideEndOfChamferFace)) {
|
|
252823
|
+
nodeP.setMask(this._breakMaskA);
|
|
252824
|
+
nodeP.setMask(this._breakMaskB);
|
|
252825
|
+
}
|
|
252826
|
+
else if (nodeP.isMaskSet(this._insideChamferSling)) {
|
|
252827
|
+
// This is the sling. It's normal is along edge -- not really a break.
|
|
252828
|
+
}
|
|
252829
|
+
else if (nodeP.isMaskSet(this._insideOfChamferFace)) {
|
|
252830
|
+
nodeP.setMask(this._breakMaskA);
|
|
252831
|
+
nodeP.setMask(this._breakMaskB);
|
|
252832
|
+
nodeR.setMask(this._breakMaskB);
|
|
252833
|
+
}
|
|
252834
|
+
else if (nodeQ.isMaskSet(this._exteriorMask)) {
|
|
252835
|
+
numBreaks++;
|
|
252836
|
+
nodeP.setMask(this._breakMaskA);
|
|
252837
|
+
}
|
|
252838
|
+
else if (!SectorOffsetProperties.almostEqualNormals(nodeP.edgeTag, nodeR.edgeTag, smoothSingleSmoothRadiansBetweenNormals)) {
|
|
252839
|
+
nodeP.setMask(this._breakMaskA);
|
|
252840
|
+
numBreaks++;
|
|
252841
|
+
nodeR.setMask(this._breakMaskB);
|
|
252842
|
+
}
|
|
252843
|
+
else {
|
|
252844
|
+
_numSmooth++;
|
|
252845
|
+
}
|
|
252846
|
+
}
|
|
252847
|
+
nodeP = nodeP.vertexSuccessor;
|
|
252848
|
+
} while (nodeP !== vertexSeed);
|
|
252849
|
+
if (OffsetMeshContext.stringDebugFunction !== undefined)
|
|
252850
|
+
OffsetMeshContext.stringDebugFunction(` numSkip ${_numSmooth} `);
|
|
252851
|
+
if (numBreaks === 0) {
|
|
252852
|
+
// make the first vertex a break so subsequent searches have a place to start
|
|
252853
|
+
vertexSeed.setMask(this._breakMaskA);
|
|
252854
|
+
vertexSeed.vertexPredecessor.setMask(this._breakMaskB);
|
|
252855
|
+
numBreaks = 1;
|
|
252856
|
+
}
|
|
252857
|
+
// Step 2: At each single break, sweep forward to its closing breakB. Insert breaks at accumulated angles.
|
|
252858
|
+
// (minor TODO: for the insertion case, try to split more equally.)
|
|
252859
|
+
const nodeAStart = nodeP.findMaskAroundVertex(this._breakMaskA);
|
|
252860
|
+
if (nodeAStart !== undefined) {
|
|
252861
|
+
nodeP = nodeAStart;
|
|
252862
|
+
do {
|
|
252863
|
+
if (nodeP.isMaskSet(this._breakMaskA) && !nodeP.isMaskSet(this._breakMaskB)) {
|
|
252864
|
+
let accumulatedRadians = 0.0;
|
|
252865
|
+
do {
|
|
252866
|
+
const nodeB = nodeP.vertexSuccessor;
|
|
252867
|
+
accumulatedRadians += SectorOffsetProperties.radiansBetweenNormals(nodeP.edgeTag, nodeB.edgeTag);
|
|
252868
|
+
if (accumulatedRadians > accumulatedRadiansBetweenNormals) {
|
|
252869
|
+
nodeP.setMask(this._breakMaskB);
|
|
252870
|
+
nodeB.setMask(this._breakMaskA);
|
|
252871
|
+
numBreaks++;
|
|
252872
|
+
accumulatedRadians = 0.0;
|
|
252873
|
+
}
|
|
252874
|
+
nodeP = nodeB;
|
|
252875
|
+
} while (!nodeP.isMaskSet(this._breakMaskB));
|
|
252876
|
+
}
|
|
252877
|
+
else {
|
|
252878
|
+
nodeP = nodeP.vertexSuccessor;
|
|
252879
|
+
}
|
|
252880
|
+
} while (nodeP !== nodeAStart);
|
|
252881
|
+
}
|
|
252882
|
+
if (numBreaks > 0 && nodeAStart !== undefined) {
|
|
252883
|
+
// In each compound sector, accumulate and install average normal.
|
|
252884
|
+
nodeP = nodeAStart;
|
|
252885
|
+
const averageNormal = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Vector3d.create();
|
|
252886
|
+
const edgeVectorU = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Vector3d.create();
|
|
252887
|
+
const edgeVectorV = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Vector3d.create();
|
|
252888
|
+
averageNormal.setZero();
|
|
252889
|
+
do {
|
|
252890
|
+
if (nodeP.isMaskSet(this._breakMaskA) && !nodeP.isMaskSet(this._breakMaskB)) {
|
|
252891
|
+
let nodeQ = nodeP;
|
|
252892
|
+
averageNormal.setZero();
|
|
252893
|
+
for (;;) {
|
|
252894
|
+
nodeQ.vectorToFaceSuccessor(edgeVectorU);
|
|
252895
|
+
nodeQ.vectorToFacePredecessor(edgeVectorV);
|
|
252896
|
+
let singleSectorRadians = edgeVectorU.signedRadiansTo(edgeVectorV, nodeQ.faceTag.facetNormal.direction);
|
|
252897
|
+
if (singleSectorRadians < 0.0)
|
|
252898
|
+
singleSectorRadians += Math.PI * 2;
|
|
252899
|
+
SectorOffsetProperties.accumulateScaledNormalAtHalfEdge(nodeQ, singleSectorRadians, averageNormal);
|
|
252900
|
+
if (nodeQ.isMaskSet(this._breakMaskB))
|
|
252901
|
+
break;
|
|
252902
|
+
nodeQ = nodeQ.vertexSuccessor;
|
|
252903
|
+
}
|
|
252904
|
+
if (averageNormal.normalizeInPlace()) {
|
|
252905
|
+
nodeQ = nodeP;
|
|
252906
|
+
for (;;) {
|
|
252907
|
+
SectorOffsetProperties.setNormalAtHalfEdge(nodeQ, averageNormal);
|
|
252908
|
+
if (nodeQ.isMaskSet(this._breakMaskB))
|
|
252909
|
+
break;
|
|
252910
|
+
nodeQ = nodeQ.vertexSuccessor;
|
|
252911
|
+
}
|
|
252912
|
+
}
|
|
252913
|
+
}
|
|
252914
|
+
nodeP = nodeP.vertexSuccessor;
|
|
252915
|
+
} while (nodeP !== nodeAStart);
|
|
252916
|
+
}
|
|
252917
|
+
}
|
|
252918
|
+
/** Compute the point of intersection of the planes in the sectors of 3 half edges */
|
|
252919
|
+
compute3SectorIntersection(nodeA, nodeB, nodeC, result) {
|
|
252920
|
+
const sectorA = nodeA.edgeTag;
|
|
252921
|
+
const sectorB = nodeB.edgeTag;
|
|
252922
|
+
const sectorC = nodeC.edgeTag;
|
|
252923
|
+
const vector = _numerics_Polynomials__WEBPACK_IMPORTED_MODULE_7__.SmallSystem.intersect3Planes(sectorA.xyz, sectorA.normal, sectorB.xyz, sectorB.normal, sectorC.xyz, sectorC.normal, result);
|
|
252924
|
+
return vector;
|
|
252925
|
+
}
|
|
252926
|
+
/** Compute the point of intersection of the planes in the sectors of 3 half edges */
|
|
252927
|
+
compute3SectorIntersectionDebug(nodeA, nodeB, nodeC, result) {
|
|
252928
|
+
const sectorA = nodeA.edgeTag;
|
|
252929
|
+
const sectorB = nodeB.edgeTag;
|
|
252930
|
+
const sectorC = nodeC.edgeTag;
|
|
252931
|
+
if (OffsetMeshContext.stringDebugFunction !== undefined) {
|
|
252932
|
+
OffsetMeshContext.stringDebugFunction(`compute3${this.inspectMasks(nodeA)}${this.inspectMasks(nodeB)}${this.inspectMasks(nodeC)} `);
|
|
252933
|
+
for (const sector of [sectorA, sectorB, sectorC])
|
|
252934
|
+
emitSector(sector);
|
|
252935
|
+
}
|
|
252936
|
+
const vector = _numerics_Polynomials__WEBPACK_IMPORTED_MODULE_7__.SmallSystem.intersect3Planes(sectorA.xyz, sectorA.normal, sectorB.xyz, sectorB.normal, sectorC.xyz, sectorC.normal, result);
|
|
252937
|
+
if (OffsetMeshContext.stringDebugFunction !== undefined) {
|
|
252938
|
+
if (vector === undefined)
|
|
252939
|
+
OffsetMeshContext.stringDebugFunction(" NO INTERSECTION");
|
|
252940
|
+
else
|
|
252941
|
+
OffsetMeshContext.stringDebugFunction(` ComputedVector ${vector.x},${vector.y},${vector.z} `);
|
|
252942
|
+
}
|
|
252943
|
+
return vector;
|
|
252944
|
+
}
|
|
252945
|
+
/** Compute the point of intersection of the planes in the sectors of 2 half edges, using cross product of their normals to resolve */
|
|
252946
|
+
compute2SectorIntersection(nodeA, nodeB, result) {
|
|
252947
|
+
const sectorA = nodeA.edgeTag;
|
|
252948
|
+
const sectorB = nodeB.edgeTag;
|
|
252949
|
+
const normalC = sectorA.normal.crossProduct(sectorB.normal);
|
|
252950
|
+
return _numerics_Polynomials__WEBPACK_IMPORTED_MODULE_7__.SmallSystem.intersect3Planes(sectorA.xyz, sectorA.normal, sectorB.xyz, sectorB.normal, sectorB.xyz, normalC, result);
|
|
252951
|
+
}
|
|
252952
|
+
/**
|
|
252953
|
+
* * at input, graph has all original faces and edges
|
|
252954
|
+
* * each sector points to a faceProperties with original facet normal
|
|
252955
|
+
* * at exit:
|
|
252956
|
+
* * new "chamfer faces" are added outside of edges with angle between normal sin excess of options.chamferTurnAngleBetweenNormals
|
|
252957
|
+
* * the original edge is split along its length to create space
|
|
252958
|
+
* * one edge "along" each direction inside the slit.
|
|
252959
|
+
* * a sling edge at each end of the slit.
|
|
252960
|
+
* * outside of the sling is part of the slit face loop.
|
|
252961
|
+
* * inside is a single-node face
|
|
252962
|
+
* * thus the slit itself has 4 nodes.
|
|
252963
|
+
* * the two nodes at each end can thus contain the two distinct points at that end of the chamfer.
|
|
252964
|
+
* * all 4 nodes of the slit face point to a new FacetOffsetProperties with the average normal.
|
|
252965
|
+
* * the inside of each sling face has
|
|
252966
|
+
* * original vertex coordinates in the node
|
|
252967
|
+
* * face properties with a normal pointing outward from that end of the original edge -- hence define a plane that can clip the chamfer
|
|
252968
|
+
* * the two points at each end of the chamfer are computed as the intersection of
|
|
252969
|
+
* * chamfer plane
|
|
252970
|
+
* * sling plane
|
|
252971
|
+
* * adjacent plane of the face on the other side of the edge being chamfered.
|
|
252972
|
+
* @param distance distance to offset. The sign of this is important in the chamfer construction.
|
|
252973
|
+
*/
|
|
252974
|
+
addChamferTopologyToAllEdges(options, distance) {
|
|
252975
|
+
const edgesToChamfer = [];
|
|
252976
|
+
const chamferRadians = options.chamferAngleBetweenNormals.radians;
|
|
252977
|
+
const vertexXYZ = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Point3d.create(); // reuse
|
|
252978
|
+
const edgeVector = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Vector3d.create(); // reuse
|
|
252979
|
+
const outwardEdgeVector = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Vector3d.create(); // reuse
|
|
252980
|
+
const averageNormal = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Vector3d.create(); // reuse
|
|
252981
|
+
// collect all the edges with sharp turn angle.
|
|
252982
|
+
this._baseGraph.announceEdges((_graph, edgeNode) => {
|
|
252983
|
+
if (SectorOffsetProperties.edgeHasLargeExteriorAngleBetweenNormals(edgeNode, edgeVector, averageNormal, distance, chamferRadians)) {
|
|
252984
|
+
edgesToChamfer.push(edgeNode);
|
|
252985
|
+
return true;
|
|
252986
|
+
}
|
|
252987
|
+
return true;
|
|
252988
|
+
});
|
|
252989
|
+
// Create sliver faces.
|
|
252990
|
+
// Sliver face gets an average normal from its neighbors.
|
|
252991
|
+
// outsideA is the HalfEdge labeled A in the diagram.
|
|
252992
|
+
// sliverDX and sliverDY are the edges "inside the sliver" at the respective X and Y ends.
|
|
252993
|
+
for (const outsideA of edgesToChamfer) {
|
|
252994
|
+
// remark: this recomputes as in collection round.
|
|
252995
|
+
if (SectorOffsetProperties.edgeHasLargeExteriorAngleBetweenNormals(outsideA, edgeVector, averageNormal, chamferRadians)) {
|
|
252996
|
+
// This copies coordinates and vertex id .... sectorOffsetProperties are delayed until late in the 2-pass loop below.
|
|
252997
|
+
// The returned HalfEdge is labeled D in the diagram
|
|
252998
|
+
const sliverDX = this._baseGraph.splitEdgeCreateSliverFace(outsideA);
|
|
252999
|
+
const sliverDY = sliverDX.facePredecessor;
|
|
253000
|
+
const offsetPoint = sliverDX.getPoint3d();
|
|
253001
|
+
offsetPoint.addScaledInPlace(averageNormal, distance);
|
|
253002
|
+
const ray = _geometry3d_Ray3d__WEBPACK_IMPORTED_MODULE_8__.Ray3d.createCapture(offsetPoint, averageNormal.clone());
|
|
253003
|
+
const facetProperties = new FacetOffsetProperties(-1, ray);
|
|
253004
|
+
// for each side (hence end) of the sliver face, set mask and install a sling loop for the anticipated end of the chamfer face
|
|
253005
|
+
// new node names in the loop omit X or Y suffix because that is implied by which pass is running.
|
|
253006
|
+
let s = -1.0;
|
|
253007
|
+
for (const sliverD of [sliverDX, sliverDY]) {
|
|
253008
|
+
edgeVector.scale(s, outwardEdgeVector);
|
|
253009
|
+
sliverD.getPoint3d(vertexXYZ);
|
|
253010
|
+
sliverD.setMask(this._insideOfChamferFace);
|
|
253011
|
+
sliverD.edgeMate.setMask(this._outsideOfChamferFace);
|
|
253012
|
+
// mark and reference the chamfer face.
|
|
253013
|
+
sliverD.faceTag = facetProperties;
|
|
253014
|
+
// sling at this end
|
|
253015
|
+
const slingB = this._baseGraph.splitEdge(undefined, vertexXYZ.x, vertexXYZ.y, vertexXYZ.z, sliverD.i);
|
|
253016
|
+
const slingC = slingB.edgeMate;
|
|
253017
|
+
slingB.setMask(this._outsideEndOfChamferFace);
|
|
253018
|
+
slingB.faceTag = facetProperties;
|
|
253019
|
+
slingC.setMask(this._insideChamferSling);
|
|
253020
|
+
_topology_Graph__WEBPACK_IMPORTED_MODULE_1__.HalfEdge.pinch(sliverD, slingB);
|
|
253021
|
+
const endNormal = _geometry3d_Ray3d__WEBPACK_IMPORTED_MODULE_8__.Ray3d.create(vertexXYZ, outwardEdgeVector); // clones the inputs
|
|
253022
|
+
const slingFaceProperties = new FacetOffsetProperties(-1, endNormal);
|
|
253023
|
+
slingC.faceTag = slingFaceProperties;
|
|
253024
|
+
// initialize sectors with existing vertex point.
|
|
253025
|
+
sliverD.edgeTag = new SectorOffsetProperties(averageNormal.clone(), offsetPoint.clone());
|
|
253026
|
+
slingB.edgeTag = new SectorOffsetProperties(averageNormal.clone(), offsetPoint.clone());
|
|
253027
|
+
slingC.edgeTag = new SectorOffsetProperties(outwardEdgeVector.clone(), vertexXYZ.clone());
|
|
253028
|
+
// OffsetMeshContext.stringDebugFunction("Chamfer Setup");
|
|
253029
|
+
const chamferPointE = this.compute3SectorIntersection(sliverD, sliverD.edgeMate, slingC);
|
|
253030
|
+
const chamferPointF = this.compute3SectorIntersection(slingB, slingB.vertexSuccessor, slingC);
|
|
253031
|
+
// sliverD.edgeTag = new SectorOffsetProperties(averageNormal.clone(), vertexXYZ.clone());
|
|
253032
|
+
SectorOffsetProperties.setXYZAtHalfEdge(sliverD, chamferPointE);
|
|
253033
|
+
SectorOffsetProperties.setXYZAtHalfEdge(slingB, chamferPointF);
|
|
253034
|
+
s *= -1.0;
|
|
253035
|
+
}
|
|
253036
|
+
}
|
|
253037
|
+
}
|
|
253038
|
+
}
|
|
253039
|
+
/**
|
|
253040
|
+
* * at input:
|
|
253041
|
+
* * Each node points to sectorOffsetProperties with previously computed XYZ (presumably mismatched)
|
|
253042
|
+
* * at exit:
|
|
253043
|
+
* * Each sectorOffsetProperties has an offset point computed with consideration of offset planes in the neighborhood.
|
|
253044
|
+
* @param distance distance to offset.
|
|
253045
|
+
*/
|
|
253046
|
+
computeOffsetFacetIntersections(distance) {
|
|
253047
|
+
if (OffsetMeshContext.stringDebugFunction !== undefined)
|
|
253048
|
+
OffsetMeshContext.stringDebugFunction("***** recompute intersections");
|
|
253049
|
+
const breakEdges = [];
|
|
253050
|
+
const vertexXYZ = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Point3d.create();
|
|
253051
|
+
const chamferXYZ = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_0__.Point3d.create();
|
|
253052
|
+
const maxVertexMove = 2.0 * distance;
|
|
253053
|
+
const averageNormalData = new AverageNormalData();
|
|
253054
|
+
const maxAllowedNormalDeviationRadians = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_9__.Angle.degreesToRadians(25.0);
|
|
253055
|
+
//
|
|
253056
|
+
// FOR EACH VERTEX
|
|
253057
|
+
//
|
|
253058
|
+
this._baseGraph.announceVertexLoops((_graph, vertexSeedA) => {
|
|
253059
|
+
// reposition to an important vertex.
|
|
253060
|
+
// first choice: a chamfer face.
|
|
253061
|
+
let vertexSeed = vertexSeedA.findMaskAroundVertex(this._outsideEndOfChamferFace);
|
|
253062
|
+
if (vertexSeed === undefined)
|
|
253063
|
+
vertexSeed = vertexSeedA.findMaskAroundVertex(this._breakMaskA);
|
|
253064
|
+
if (vertexSeed === undefined)
|
|
253065
|
+
vertexSeed = vertexSeedA;
|
|
253066
|
+
if (OffsetMeshContext.stringDebugFunction !== undefined) {
|
|
253067
|
+
OffsetMeshContext.stringDebugFunction("");
|
|
253068
|
+
OffsetMeshContext.stringDebugFunction(` VERTEX LOOP ${vertexSeed.getPoint3d().toJSON()} `);
|
|
253069
|
+
vertexSeed.sumAroundVertex((node) => { OffsetMeshContext.stringDebugFunction(this.inspectMasks(node, false, true)); return 0; });
|
|
253070
|
+
}
|
|
253071
|
+
// Take care of the easiest vertices directly . . . note that this returns from the lambda, not computeOffsetFacetIntersections
|
|
253072
|
+
if (this.assignOffsetByAverageNormalAroundVertex(vertexSeed, maxAllowedNormalDeviationRadians, averageNormalData, distance))
|
|
253073
|
+
return true;
|
|
253074
|
+
this.markBreakEdgesAndSaveAverageNormalsAroundVertex(vertexSeed);
|
|
253075
|
+
this.setOffsetAtDistanceAroundVertex(vertexSeed, distance, true);
|
|
253076
|
+
vertexSeed.collectMaskedEdgesAroundVertex(this._breakMaskA, true, breakEdges);
|
|
253077
|
+
if (OffsetMeshContext.stringDebugFunction !== undefined) {
|
|
253078
|
+
OffsetMeshContext.stringDebugFunction(` BREAK EDGES from ${this.inspectMasks(vertexSeed, true, false)}`);
|
|
253079
|
+
for (const node of breakEdges) {
|
|
253080
|
+
OffsetMeshContext.stringDebugFunction(this.inspectMasks(node, false, true));
|
|
253081
|
+
}
|
|
253082
|
+
}
|
|
253083
|
+
if (breakEdges.length <= 1) {
|
|
253084
|
+
// just one smooth sequence.
|
|
253085
|
+
// everything is set already.
|
|
253086
|
+
}
|
|
253087
|
+
else if (breakEdges.length === 2) {
|
|
253088
|
+
// exterior vertex with two incident smooth
|
|
253089
|
+
const vectorFromOrigin = this.compute2SectorIntersection(breakEdges[0], breakEdges[1]);
|
|
253090
|
+
if (vectorFromOrigin !== undefined) {
|
|
253091
|
+
this.setOffsetXYAndZAroundVertex(vertexSeed, vectorFromOrigin);
|
|
253092
|
+
}
|
|
253093
|
+
}
|
|
253094
|
+
else if (breakEdges.length === 3) {
|
|
253095
|
+
if (OffsetMeshContext.stringDebugFunction !== undefined)
|
|
253096
|
+
OffsetMeshContext.stringDebugFunction(` Vertex Update just ${breakEdges.length} `);
|
|
253097
|
+
const vectorFromOrigin = this.compute3SectorIntersection(breakEdges[0], breakEdges[1], breakEdges[2]);
|
|
253098
|
+
if (vectorFromOrigin !== undefined) {
|
|
253099
|
+
this.setOffsetXYAndZAroundVertex(vertexSeed, vectorFromOrigin);
|
|
253100
|
+
}
|
|
253101
|
+
// simple 3-face corner . . .
|
|
253102
|
+
}
|
|
253103
|
+
else {
|
|
253104
|
+
// Lots and Lots of edges
|
|
253105
|
+
// each set of 3 sectors independently generates an offset for its central sector.
|
|
253106
|
+
if (OffsetMeshContext.stringDebugFunction !== undefined)
|
|
253107
|
+
OffsetMeshContext.stringDebugFunction(` Vertex Update breakEdges ${breakEdges.length} `);
|
|
253108
|
+
vertexSeed.getPoint3d(vertexXYZ);
|
|
253109
|
+
// Pass 1 -- look for intersection among multiple chamfers
|
|
253110
|
+
for (let i = 0; i < breakEdges.length; i++) {
|
|
253111
|
+
const i0 = i;
|
|
253112
|
+
const i1 = (i0 + 1) % breakEdges.length;
|
|
253113
|
+
const i2 = (i1 + 1) % breakEdges.length;
|
|
253114
|
+
if (breakEdges[i0].isMaskSet(this._outsideEndOfChamferFace)
|
|
253115
|
+
&& breakEdges[i1].isMaskSet(this._outsideOfChamferFace)
|
|
253116
|
+
&& breakEdges[i2].isMaskSet(this._insideOfChamferFace)) {
|
|
253117
|
+
if (OffsetMeshContext.stringDebugFunction !== undefined)
|
|
253118
|
+
OffsetMeshContext.stringDebugFunction(` ChamferChamfer Fixup ${this.inspectMasks(breakEdges[i0])} ${this.inspectMasks(breakEdges[i1])} ${this.inspectMasks(breakEdges[i2])} `);
|
|
253119
|
+
const vectorFromOrigin = this.compute3SectorIntersection(breakEdges[i0], breakEdges[i1], breakEdges[i2]);
|
|
253120
|
+
if (vectorFromOrigin !== undefined) {
|
|
253121
|
+
// Treat all 3 spots as possibly compound sequences
|
|
253122
|
+
for (const iOutput of [i0, i1, i2]) {
|
|
253123
|
+
this.announceNodeAndSectorPropertiesInSmoothSector(breakEdges[iOutput], (node, properties) => {
|
|
253124
|
+
properties.setXYAndZ(vectorFromOrigin);
|
|
253125
|
+
node.setMask(this._offsetCoordinatesReassigned);
|
|
253126
|
+
});
|
|
253127
|
+
}
|
|
253128
|
+
// Since all three were reset, skip past. This is done on the acyclic integer that controls the loop.
|
|
253129
|
+
i += 2;
|
|
253130
|
+
}
|
|
253131
|
+
}
|
|
253132
|
+
}
|
|
253133
|
+
// Pass 2 -- look for unassigned nodes just before or after a chamfer.
|
|
253134
|
+
// The chamfer wins
|
|
253135
|
+
for (let i = 0; i < breakEdges.length; i++) {
|
|
253136
|
+
const i0 = i;
|
|
253137
|
+
const i1 = (i0 + 1) % breakEdges.length;
|
|
253138
|
+
if (this.isInsideSling(breakEdges[i0], breakEdges[i1]))
|
|
253139
|
+
continue;
|
|
253140
|
+
if (!this.isOffsetAssigned(breakEdges[i0])
|
|
253141
|
+
&& breakEdges[i1].isMaskSet(this.insideOfChamferFace)) {
|
|
253142
|
+
this.transferXYZFromNodeToSmoothSector(breakEdges[i1], breakEdges[i0], "push left from chamfer", chamferXYZ);
|
|
253143
|
+
}
|
|
253144
|
+
else if (!this.isOffsetAssigned(breakEdges[i1])
|
|
253145
|
+
&& breakEdges[i0].isMaskSet(this.outsideEndOfChamferFace)) {
|
|
253146
|
+
this.transferXYZFromNodeToSmoothSector(breakEdges[i0], breakEdges[i1], "push right from chamfer", chamferXYZ);
|
|
253147
|
+
}
|
|
253148
|
+
}
|
|
253149
|
+
// Pass 3 -- look for unassigned nodes as middle of 3-face intersections
|
|
253150
|
+
for (let i = 0; i < breakEdges.length; i++) {
|
|
253151
|
+
const i0 = i;
|
|
253152
|
+
const i1 = (i0 + 1) % breakEdges.length;
|
|
253153
|
+
const i2 = (i1 + 1) % breakEdges.length;
|
|
253154
|
+
if (this.isInsideSling(breakEdges[i0], breakEdges[i1], breakEdges[i2]))
|
|
253155
|
+
continue;
|
|
253156
|
+
if (this.isOffsetAssigned(breakEdges[i1]))
|
|
253157
|
+
continue;
|
|
253158
|
+
if (OffsetMeshContext.stringDebugFunction !== undefined)
|
|
253159
|
+
OffsetMeshContext.stringDebugFunction(` Intersection Fixup ${this.inspectMasks(breakEdges[i0])} ${this.inspectMasks(breakEdges[i1])} ${this.inspectMasks(breakEdges[i2])} `);
|
|
253160
|
+
const vectorFromOrigin = this.compute3SectorIntersection(breakEdges[i0], breakEdges[i1], breakEdges[i2]);
|
|
253161
|
+
if (vectorFromOrigin !== undefined) {
|
|
253162
|
+
if (vertexXYZ.distance(vectorFromOrigin) < maxVertexMove) {
|
|
253163
|
+
this.announceNodeAndSectorPropertiesInSmoothSector(breakEdges[i1], (node, properties) => {
|
|
253164
|
+
properties.setXYAndZ(vectorFromOrigin);
|
|
253165
|
+
node.setMask(this._offsetCoordinatesReassigned);
|
|
253166
|
+
});
|
|
253167
|
+
}
|
|
253168
|
+
}
|
|
253169
|
+
}
|
|
253170
|
+
}
|
|
253171
|
+
if (OffsetMeshContext.stringDebugFunction !== undefined) {
|
|
253172
|
+
const n0 = vertexSeed.countMaskAroundVertex(this._offsetCoordinatesReassigned, false);
|
|
253173
|
+
const n1 = vertexSeed.countMaskAroundVertex(this._offsetCoordinatesReassigned, true);
|
|
253174
|
+
const message = ` **** Vertex offset mask counts(TRUE ${n1})(FALSE ${n0})`;
|
|
253175
|
+
OffsetMeshContext.stringDebugFunction(message);
|
|
253176
|
+
}
|
|
253177
|
+
return true;
|
|
253178
|
+
});
|
|
253179
|
+
}
|
|
253180
|
+
// return true if any of these nodes is "inside" the sling at the end of a chamfer.
|
|
253181
|
+
isInsideSling(node0, node1, node2) {
|
|
253182
|
+
return node0.isMaskSet(this._insideChamferSling)
|
|
253183
|
+
|| (node1 !== undefined && node1.isMaskSet(this._insideChamferSling))
|
|
253184
|
+
|| (node2 !== undefined && node2.isMaskSet(this._insideChamferSling));
|
|
253185
|
+
}
|
|
253186
|
+
// return true if any of these nodes is "inside" the sling at the end of a chamfer.
|
|
253187
|
+
isInsideChamferOrSling(node0) {
|
|
253188
|
+
return node0.isMaskSet(this._insideChamferSling)
|
|
253189
|
+
|| node0.isMaskSet(this._insideOfChamferFace)
|
|
253190
|
+
|| node0.isMaskSet(this._outsideEndOfChamferFace);
|
|
253191
|
+
}
|
|
253192
|
+
isOffsetAssigned(node0, node1, node2) {
|
|
253193
|
+
return node0.isMaskSet(this._offsetCoordinatesReassigned)
|
|
253194
|
+
|| (node1 !== undefined && node1.isMaskSet(this._offsetCoordinatesReassigned))
|
|
253195
|
+
|| (node2 !== undefined && node2.isMaskSet(this._offsetCoordinatesReassigned));
|
|
253196
|
+
}
|
|
253197
|
+
/**
|
|
253198
|
+
*
|
|
253199
|
+
* @param sourceNode node with good xyz
|
|
253200
|
+
* @param destinationStartNode first of a sequence of nodes to set (delimited by masks)
|
|
253201
|
+
* @param description string for debug
|
|
253202
|
+
* @param workPoint point to use for coordinate transfer.
|
|
253203
|
+
*/
|
|
253204
|
+
transferXYZFromNodeToSmoothSector(sourceNode, destinationStartNode, description, workPoint) {
|
|
253205
|
+
if (OffsetMeshContext.stringDebugFunction !== undefined)
|
|
253206
|
+
OffsetMeshContext.stringDebugFunction(` ${description} ${this.inspectMasks(sourceNode)} to ${this.inspectMasks(destinationStartNode)}} `);
|
|
253207
|
+
SectorOffsetProperties.getSectorPointAtHalfEdge(sourceNode, workPoint, undefined);
|
|
253208
|
+
this.announceNodeAndSectorPropertiesInSmoothSector(destinationStartNode, (node, properties) => {
|
|
253209
|
+
properties.setXYAndZ(workPoint);
|
|
253210
|
+
node.setMask(this._offsetCoordinatesReassigned);
|
|
253211
|
+
});
|
|
253212
|
+
}
|
|
253213
|
+
}
|
|
253214
|
+
|
|
253215
|
+
|
|
251963
253216
|
/***/ }),
|
|
251964
253217
|
|
|
251965
253218
|
/***/ "../../core/geometry/lib/esm/polyface/multiclip/RangeSearch.js":
|
|
@@ -261168,16 +262421,16 @@ class Sample {
|
|
|
261168
262421
|
_curve_Arc3d__WEBPACK_IMPORTED_MODULE_20__.Arc3d.createXY(_geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(5, 0), 5, _geometry3d_AngleSweep__WEBPACK_IMPORTED_MODULE_0__.AngleSweep.createStartEndDegrees(180, 0)), _curve_Arc3d__WEBPACK_IMPORTED_MODULE_20__.Arc3d.createXY(_geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(15, 0), 5, _geometry3d_AngleSweep__WEBPACK_IMPORTED_MODULE_0__.AngleSweep.createStartEndDegrees(180, 360)), _curve_Arc3d__WEBPACK_IMPORTED_MODULE_20__.Arc3d.createXY(_geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(25, 0), 5, _geometry3d_AngleSweep__WEBPACK_IMPORTED_MODULE_0__.AngleSweep.createStartEndDegrees(180, 0)))));
|
|
261169
262422
|
result.push(_curve_CurveChainWithDistanceIndex__WEBPACK_IMPORTED_MODULE_44__.CurveChainWithDistanceIndex.createCapture(_curve_Path__WEBPACK_IMPORTED_MODULE_21__.Path.create(// 2-pt Interpolation Curve
|
|
261170
262423
|
_bspline_InterpolationCurve3d__WEBPACK_IMPORTED_MODULE_45__.InterpolationCurve3d.createCapture(_bspline_InterpolationCurve3d__WEBPACK_IMPORTED_MODULE_45__.InterpolationCurve3dOptions.create({
|
|
261171
|
-
fitPoints: [pointsA[0], pointsA[1]]
|
|
262424
|
+
fitPoints: [pointsA[0], pointsA[1]],
|
|
261172
262425
|
})))));
|
|
261173
262426
|
result.push(_curve_CurveChainWithDistanceIndex__WEBPACK_IMPORTED_MODULE_44__.CurveChainWithDistanceIndex.createCapture(_curve_Path__WEBPACK_IMPORTED_MODULE_21__.Path.create(// 3-pt Interpolation Curve
|
|
261174
262427
|
_bspline_InterpolationCurve3d__WEBPACK_IMPORTED_MODULE_45__.InterpolationCurve3d.createCapture(_bspline_InterpolationCurve3d__WEBPACK_IMPORTED_MODULE_45__.InterpolationCurve3dOptions.create({
|
|
261175
|
-
fitPoints: [pointsA[0], pointsA[1], pointsA[2]]
|
|
262428
|
+
fitPoints: [pointsA[0], pointsA[1], pointsA[2]],
|
|
261176
262429
|
})))));
|
|
261177
262430
|
result.push(_curve_CurveChainWithDistanceIndex__WEBPACK_IMPORTED_MODULE_44__.CurveChainWithDistanceIndex.createCapture(_curve_Path__WEBPACK_IMPORTED_MODULE_21__.Path.create(_bspline_InterpolationCurve3d__WEBPACK_IMPORTED_MODULE_45__.InterpolationCurve3d.createCapture(_bspline_InterpolationCurve3d__WEBPACK_IMPORTED_MODULE_45__.InterpolationCurve3dOptions.create({
|
|
261178
262431
|
fitPoints: pointsA,
|
|
261179
262432
|
startTangent: _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(1, -1),
|
|
261180
|
-
endTangent: _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(-1, -1)
|
|
262433
|
+
endTangent: _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(-1, -1),
|
|
261181
262434
|
})))));
|
|
261182
262435
|
result.push(_curve_CurveChainWithDistanceIndex__WEBPACK_IMPORTED_MODULE_44__.CurveChainWithDistanceIndex.createCapture(_curve_Path__WEBPACK_IMPORTED_MODULE_21__.Path.create(_curve_spiral_IntegratedSpiral3d__WEBPACK_IMPORTED_MODULE_39__.IntegratedSpiral3d.createRadiusRadiusBearingBearing(_geometry3d_Segment1d__WEBPACK_IMPORTED_MODULE_40__.Segment1d.create(0, 100), _geometry3d_AngleSweep__WEBPACK_IMPORTED_MODULE_0__.AngleSweep.createStartEndDegrees(10, 75), _geometry3d_Segment1d__WEBPACK_IMPORTED_MODULE_40__.Segment1d.create(0, 1), _geometry3d_Transform__WEBPACK_IMPORTED_MODULE_16__.Transform.createOriginAndMatrix(_geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.createZero(), _geometry3d_Matrix3d__WEBPACK_IMPORTED_MODULE_12__.Matrix3d.createRotationAroundAxisIndex(2, _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_3__.Angle.createDegrees(30))), "bloss"))));
|
|
261183
262436
|
result.push(_curve_CurveChainWithDistanceIndex__WEBPACK_IMPORTED_MODULE_44__.CurveChainWithDistanceIndex.createCapture(_curve_Path__WEBPACK_IMPORTED_MODULE_21__.Path.create(_curve_spiral_DirectSpiral3d__WEBPACK_IMPORTED_MODULE_41__.DirectSpiral3d.createDirectHalfCosine(_geometry3d_Transform__WEBPACK_IMPORTED_MODULE_16__.Transform.createOriginAndMatrix(_geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.createZero(), _geometry3d_Matrix3d__WEBPACK_IMPORTED_MODULE_12__.Matrix3d.createRotationAroundAxisIndex(2, _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_3__.Angle.createDegrees(110))), 50, 350, _geometry3d_Segment1d__WEBPACK_IMPORTED_MODULE_40__.Segment1d.create(0, 1)))));
|
|
@@ -261291,8 +262544,11 @@ class Sample {
|
|
|
261291
262544
|
/** Create swept "solids" that can be capped.
|
|
261292
262545
|
* * At least one of each solid type.
|
|
261293
262546
|
* * each is within 10 of the origin all directions.
|
|
262547
|
+
* @param capped true to include caps
|
|
262548
|
+
* @param rotationAngle angle of rotation for the angular sweep. The default is 90 degrees.
|
|
262549
|
+
* Beware that the rotation sweep created with the default or any positive angle produces a mesh with inward normals.
|
|
261294
262550
|
*/
|
|
261295
|
-
static createClosedSolidSampler(capped) {
|
|
262551
|
+
static createClosedSolidSampler(capped, rotationAngle = _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_3__.Angle.createDegrees(90)) {
|
|
261296
262552
|
const result = [];
|
|
261297
262553
|
result.push(_solid_Box__WEBPACK_IMPORTED_MODULE_35__.Box.createRange(_geometry3d_Range__WEBPACK_IMPORTED_MODULE_4__.Range3d.createXYZXYZ(0, 0, 0, 3, 2, 5), capped));
|
|
261298
262554
|
result.push(_solid_Cone__WEBPACK_IMPORTED_MODULE_33__.Cone.createAxisPoints(_geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(0, 0, 0), _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(0, 0, 5), 1.0, 1.0, capped));
|
|
@@ -261304,18 +262560,23 @@ class Sample {
|
|
|
261304
262560
|
const pointQ2 = arcA.fractionAndDistanceToPointOnTangent(1.0, 0.5);
|
|
261305
262561
|
const pointR1 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(point0.x, pointQ1.y);
|
|
261306
262562
|
const pointR2 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(point0.x, pointQ1.y);
|
|
262563
|
+
const pointR3 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(pointQ1.x - 1, pointQ1.y);
|
|
262564
|
+
const pointR4 = _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(pointQ1.x - 3, pointQ1.y);
|
|
261307
262565
|
const linestringQ1 = _curve_LineString3d__WEBPACK_IMPORTED_MODULE_15__.LineString3d.create(arcA.fractionToPoint(1.0), pointQ1, pointR1, point0);
|
|
261308
262566
|
const linestringQ2 = _curve_LineString3d__WEBPACK_IMPORTED_MODULE_15__.LineString3d.create(arcA.fractionToPoint(1.0), pointQ2, pointR2, point0);
|
|
262567
|
+
const linestringQ3 = _curve_LineString3d__WEBPACK_IMPORTED_MODULE_15__.LineString3d.create(arcA.fractionToPoint(1.0), pointQ2, pointR3, pointR4, point0);
|
|
261309
262568
|
const contourZ = _curve_Path__WEBPACK_IMPORTED_MODULE_21__.Path.create(linestringQ1.clone());
|
|
261310
262569
|
const contourA = _curve_Loop__WEBPACK_IMPORTED_MODULE_23__.Loop.create(_curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_19__.LineSegment3d.create(point0, arcA.fractionToPoint(0)), arcA.clone(), linestringQ1.clone());
|
|
261311
262570
|
const contourB = _curve_Loop__WEBPACK_IMPORTED_MODULE_23__.Loop.create(_curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_19__.LineSegment3d.create(point0, arcA.fractionToPoint(0)), arcA.clone(), linestringQ2.clone());
|
|
262571
|
+
const contourC1 = _curve_Loop__WEBPACK_IMPORTED_MODULE_23__.Loop.create(_curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_19__.LineSegment3d.create(point0, arcA.fractionToPoint(0)), arcA.clone(), linestringQ3.clone());
|
|
261312
262572
|
contourB.tryTransformInPlace(_geometry3d_Transform__WEBPACK_IMPORTED_MODULE_16__.Transform.createTranslationXYZ(1, 1, 3));
|
|
261313
262573
|
// const contourC = contourB.cloneTransformed(Transform.createTranslationXYZ(2, 1, 4))!;
|
|
261314
262574
|
result.push(_solid_LinearSweep__WEBPACK_IMPORTED_MODULE_30__.LinearSweep.create(contourA, _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Vector3d.create(0, 0, 5), capped));
|
|
262575
|
+
result.push(_solid_LinearSweep__WEBPACK_IMPORTED_MODULE_30__.LinearSweep.create(contourC1, _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Vector3d.create(0, 0, 5), capped));
|
|
261315
262576
|
const axis = _geometry3d_Ray3d__WEBPACK_IMPORTED_MODULE_14__.Ray3d.createXYZUVW(0, 8, 0, 1, 0, 0);
|
|
261316
|
-
result.push(_solid_RotationalSweep__WEBPACK_IMPORTED_MODULE_31__.RotationalSweep.create(contourA.clone(), axis.clone(),
|
|
262577
|
+
result.push(_solid_RotationalSweep__WEBPACK_IMPORTED_MODULE_31__.RotationalSweep.create(contourA.clone(), axis.clone(), rotationAngle, capped));
|
|
261317
262578
|
if (!capped)
|
|
261318
|
-
result.push(_solid_RotationalSweep__WEBPACK_IMPORTED_MODULE_31__.RotationalSweep.create(contourZ.clone(), axis.clone(),
|
|
262579
|
+
result.push(_solid_RotationalSweep__WEBPACK_IMPORTED_MODULE_31__.RotationalSweep.create(contourZ.clone(), axis.clone(), rotationAngle, false));
|
|
261319
262580
|
result.push(_solid_RuledSweep__WEBPACK_IMPORTED_MODULE_36__.RuledSweep.create([contourA.clone(), contourB.clone()], capped));
|
|
261320
262581
|
const transformC = _geometry3d_Transform__WEBPACK_IMPORTED_MODULE_16__.Transform.createScaleAboutPoint(_geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(0, 0, 8), 0.5);
|
|
261321
262582
|
const contourC = contourB.cloneTransformed(transformC);
|
|
@@ -265740,12 +267001,13 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
265740
267001
|
/* harmony export */ "HalfEdgeGraph": () => (/* binding */ HalfEdgeGraph),
|
|
265741
267002
|
/* harmony export */ "HalfEdgeMask": () => (/* binding */ HalfEdgeMask)
|
|
265742
267003
|
/* harmony export */ });
|
|
265743
|
-
/* harmony import */ var
|
|
267004
|
+
/* harmony import */ var _curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../curve/LineSegment3d */ "../../core/geometry/lib/esm/curve/LineSegment3d.js");
|
|
265744
267005
|
/* harmony import */ var _Geometry__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../Geometry */ "../../core/geometry/lib/esm/Geometry.js");
|
|
267006
|
+
/* harmony import */ var _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../geometry3d/Angle */ "../../core/geometry/lib/esm/geometry3d/Angle.js");
|
|
265745
267007
|
/* harmony import */ var _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../geometry3d/Point2dVector2d */ "../../core/geometry/lib/esm/geometry3d/Point2dVector2d.js");
|
|
265746
267008
|
/* harmony import */ var _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../geometry3d/Point3dVector3d */ "../../core/geometry/lib/esm/geometry3d/Point3dVector3d.js");
|
|
265747
|
-
/* harmony import */ var
|
|
265748
|
-
/* harmony import */ var
|
|
267009
|
+
/* harmony import */ var _numerics_Polynomials__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../numerics/Polynomials */ "../../core/geometry/lib/esm/numerics/Polynomials.js");
|
|
267010
|
+
/* harmony import */ var _MaskManager__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./MaskManager */ "../../core/geometry/lib/esm/topology/MaskManager.js");
|
|
265749
267011
|
/*---------------------------------------------------------------------------------------------
|
|
265750
267012
|
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
265751
267013
|
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
@@ -265759,6 +267021,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
265759
267021
|
|
|
265760
267022
|
|
|
265761
267023
|
|
|
267024
|
+
|
|
265762
267025
|
// import { GraphChecker } from "../test/topology/Graph.test";
|
|
265763
267026
|
/* eslint-disable @typescript-eslint/no-this-alias */
|
|
265764
267027
|
// cspell:word CONSTU
|
|
@@ -265846,6 +267109,7 @@ class HalfEdge {
|
|
|
265846
267109
|
this.sortAngle = undefined;
|
|
265847
267110
|
this.sortData = undefined;
|
|
265848
267111
|
this.edgeTag = undefined;
|
|
267112
|
+
this.faceTag = undefined;
|
|
265849
267113
|
// Always created in pairs, init here to make TS compiler and JS runtime happy
|
|
265850
267114
|
this._facePredecessor = this;
|
|
265851
267115
|
this._faceSuccessor = this;
|
|
@@ -265966,6 +267230,36 @@ class HalfEdge {
|
|
|
265966
267230
|
}
|
|
265967
267231
|
return newA;
|
|
265968
267232
|
}
|
|
267233
|
+
/**
|
|
267234
|
+
* * Create a new sliver face "inside" an existing edge.
|
|
267235
|
+
* * Insert it "within" the base edge.
|
|
267236
|
+
* * This requires two new half edges.
|
|
267237
|
+
* * if the base is undefined, create a single-edge loop.
|
|
267238
|
+
* * This (unlike pinch) breaks the edgeMate pairing of the base edge.
|
|
267239
|
+
* * This preserves xyz and i properties at all existing vertices.
|
|
267240
|
+
* * The two new half edges are a sliver face (via their predecessor and successor)
|
|
267241
|
+
* * Each new edge mates to one existing edge.
|
|
267242
|
+
* @returns Returns the reference to the half edge created.
|
|
267243
|
+
*/
|
|
267244
|
+
static splitEdgeCreateSliverFace(baseA, heArray) {
|
|
267245
|
+
// raw edges ...
|
|
267246
|
+
const newA = new HalfEdge();
|
|
267247
|
+
const newB = new HalfEdge();
|
|
267248
|
+
const baseB = baseA.edgeMate;
|
|
267249
|
+
if (heArray) {
|
|
267250
|
+
heArray.push(newA);
|
|
267251
|
+
heArray.push(newB);
|
|
267252
|
+
}
|
|
267253
|
+
newA._faceSuccessor = newA._facePredecessor = newB;
|
|
267254
|
+
newB._faceSuccessor = newB._facePredecessor = newA;
|
|
267255
|
+
// newA is in vertex loop with baseA etc.
|
|
267256
|
+
// newA mates to baseB
|
|
267257
|
+
HalfEdge.setEdgeMates(newA, baseB);
|
|
267258
|
+
HalfEdge.setEdgeMates(newB, baseA);
|
|
267259
|
+
newA.copyDataFrom(baseA, true, true, false, false);
|
|
267260
|
+
newB.copyDataFrom(baseB, true, true, false, false);
|
|
267261
|
+
return newA;
|
|
267262
|
+
}
|
|
265969
267263
|
/**
|
|
265970
267264
|
* Copy "edge based" content of fromNode to toNode
|
|
265971
267265
|
* * edgeTag
|
|
@@ -266176,6 +267470,35 @@ class HalfEdge {
|
|
|
266176
267470
|
}
|
|
266177
267471
|
return count;
|
|
266178
267472
|
}
|
|
267473
|
+
/** Returns the first node with given mask value around this vertex loop. */
|
|
267474
|
+
findMaskAroundVertex(mask, value = true) {
|
|
267475
|
+
let node = this;
|
|
267476
|
+
do {
|
|
267477
|
+
if (node.isMaskSet(mask) === value)
|
|
267478
|
+
return node;
|
|
267479
|
+
node = node.vertexSuccessor;
|
|
267480
|
+
} while (node !== this);
|
|
267481
|
+
return undefined;
|
|
267482
|
+
}
|
|
267483
|
+
/** Returns the first node with given mask value around this face loop. */
|
|
267484
|
+
findMaskAroundFace(mask, value = true) {
|
|
267485
|
+
let node = this;
|
|
267486
|
+
do {
|
|
267487
|
+
if (node.isMaskSet(mask) === value)
|
|
267488
|
+
return node;
|
|
267489
|
+
node = node.faceSuccessor;
|
|
267490
|
+
} while (node !== this);
|
|
267491
|
+
return undefined;
|
|
267492
|
+
}
|
|
267493
|
+
/** Returns the first node with given mask value on this edge (i.e. examining this and this.mate) */
|
|
267494
|
+
findMaskAroundEdge(mask, value = true) {
|
|
267495
|
+
if (this.isMaskSet(mask) === value)
|
|
267496
|
+
return this;
|
|
267497
|
+
const mate = this.edgeMate;
|
|
267498
|
+
if (mate.isMaskSet(mask) === value)
|
|
267499
|
+
return mate;
|
|
267500
|
+
return undefined;
|
|
267501
|
+
}
|
|
266179
267502
|
/** Set a mask, and return prior value.
|
|
266180
267503
|
* @param mask mask to apply
|
|
266181
267504
|
*/
|
|
@@ -266193,6 +267516,15 @@ class HalfEdge {
|
|
|
266193
267516
|
this.y = node.y;
|
|
266194
267517
|
this.z = node.z;
|
|
266195
267518
|
}
|
|
267519
|
+
/**
|
|
267520
|
+
* Set (copy) the this.x, this.y, this.z from xyz.x, xyz.y, xyz.z
|
|
267521
|
+
* @param node source with x,y,z properties
|
|
267522
|
+
*/
|
|
267523
|
+
setXYZ(xyz) {
|
|
267524
|
+
this.x = xyz.x;
|
|
267525
|
+
this.y = xyz.y;
|
|
267526
|
+
this.z = xyz.z;
|
|
267527
|
+
}
|
|
266196
267528
|
/**
|
|
266197
267529
|
* Test if mask bits are set in the node's bitMask.
|
|
266198
267530
|
* @return Return true (as a simple boolean, not a mask) if any bits of the mask parameter match bits of the node's bitMask
|
|
@@ -266282,6 +267614,10 @@ class HalfEdge {
|
|
|
266282
267614
|
const s = `${node.id.toString()}+${HalfEdge.nodeToMaskString(node)}[${node.x},${node.y}]`;
|
|
266283
267615
|
return s;
|
|
266284
267616
|
}
|
|
267617
|
+
/** Return the [id, [x,y],z] of a node. Useful for collector methods. */
|
|
267618
|
+
static nodeToIdXYZString(node) {
|
|
267619
|
+
return `[${node.id.toString()}: ${node.x},${node.y},${node.z}]`;
|
|
267620
|
+
}
|
|
266285
267621
|
/** Create a string representation of the mask
|
|
266286
267622
|
* * Null mask is empty string.
|
|
266287
267623
|
* * Appended characters B,P,X for Boundary, Primary, Exterior mask bits.
|
|
@@ -266306,7 +267642,13 @@ class HalfEdge {
|
|
|
266306
267642
|
}
|
|
266307
267643
|
/** Return Vector3d to face successor */
|
|
266308
267644
|
vectorToFaceSuccessor(result) {
|
|
266309
|
-
|
|
267645
|
+
const other = this.faceSuccessor;
|
|
267646
|
+
return _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Vector3d.create(other.x - this.x, other.y - this.y, other.z - this.z, result);
|
|
267647
|
+
}
|
|
267648
|
+
/** Return Vector3d to face successor */
|
|
267649
|
+
vectorToFacePredecessor(result) {
|
|
267650
|
+
const other = this.facePredecessor;
|
|
267651
|
+
return _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Vector3d.create(other.x - this.x, other.y - this.y, other.z - this.z, result);
|
|
266310
267652
|
}
|
|
266311
267653
|
/** test if spaceNode is in the sector at sectorNode */
|
|
266312
267654
|
static isNodeVisibleInSector(spaceNode, sectorNode) {
|
|
@@ -266430,6 +267772,14 @@ class HalfEdge {
|
|
|
266430
267772
|
static testNodeMaskNotExterior(node) { return !node.isMaskSet(HalfEdgeMask.EXTERIOR); }
|
|
266431
267773
|
/** Returns Returns true if the node does NOT have Mask.EXTERIOR_MASK set. */
|
|
266432
267774
|
static testMateMaskExterior(node) { return node.edgeMate.isMaskSet(HalfEdgeMask.EXTERIOR); }
|
|
267775
|
+
/** Returns radians between this edge and its face predecessor edge, using all three coordinates x,y,z and given normal to resolve sweep direction.
|
|
267776
|
+
* * The returned angle is positive, i.e. may be larger than PI radians.
|
|
267777
|
+
*/
|
|
267778
|
+
static sectorSweepRadiansXYZ(node, normal) {
|
|
267779
|
+
const nodeB = node.faceSuccessor;
|
|
267780
|
+
const nodeC = node.facePredecessor;
|
|
267781
|
+
return _geometry3d_Angle__WEBPACK_IMPORTED_MODULE_3__.Angle.orientedRadiansBetweenVectorsXYZ(nodeB.x - node.x, nodeB.y - node.y, nodeB.z - node.z, nodeC.x - node.x, nodeC.y - node.y, nodeC.z - node.z, normal.x, normal.y, normal.z, true);
|
|
267782
|
+
}
|
|
266433
267783
|
/** Returns Returns true if the face has positive area in xy parts. */
|
|
266434
267784
|
static testFacePositiveAreaXY(node) {
|
|
266435
267785
|
return node.countEdgesAroundFace() > 2 && node.signedFaceArea() > 0.0;
|
|
@@ -266461,6 +267811,26 @@ class HalfEdge {
|
|
|
266461
267811
|
} while (node !== this);
|
|
266462
267812
|
return nodes;
|
|
266463
267813
|
}
|
|
267814
|
+
/**
|
|
267815
|
+
* search around a vertex for nodes that have a specified mask setting.
|
|
267816
|
+
* @param vertexSeed first node to search
|
|
267817
|
+
* @param mask target mask
|
|
267818
|
+
* @param value target value for mask on half edges.
|
|
267819
|
+
* @param collectedNodes optional array to be cleared and receive masked nodes
|
|
267820
|
+
*/
|
|
267821
|
+
collectMaskedEdgesAroundVertex(mask, value = true, result) {
|
|
267822
|
+
if (result === undefined)
|
|
267823
|
+
result = [];
|
|
267824
|
+
else
|
|
267825
|
+
result.length = 0;
|
|
267826
|
+
let node = this;
|
|
267827
|
+
do {
|
|
267828
|
+
if (node.isMaskSet(mask) === value)
|
|
267829
|
+
result.push(node);
|
|
267830
|
+
node = node.vertexSuccessor;
|
|
267831
|
+
} while (node !== this);
|
|
267832
|
+
return result;
|
|
267833
|
+
}
|
|
266464
267834
|
/**
|
|
266465
267835
|
*
|
|
266466
267836
|
* * Evaluate f(node) at each outbound node around this node's vertex loop.
|
|
@@ -266644,7 +268014,7 @@ class HalfEdge {
|
|
|
266644
268014
|
const nodeB1 = nodeB0.faceSuccessor;
|
|
266645
268015
|
if (!result)
|
|
266646
268016
|
result = _geometry3d_Point2dVector2d__WEBPACK_IMPORTED_MODULE_0__.Vector2d.create();
|
|
266647
|
-
if (
|
|
268017
|
+
if (_numerics_Polynomials__WEBPACK_IMPORTED_MODULE_4__.SmallSystem.linearSystem2d(nodeA1.x - nodeA0.x, nodeB0.x - nodeB1.x, nodeA1.y - nodeA0.y, nodeB0.y - nodeB1.y, nodeB0.x - nodeA0.x, nodeB0.y - nodeA0.y, result))
|
|
266648
268018
|
return result;
|
|
266649
268019
|
return undefined;
|
|
266650
268020
|
}
|
|
@@ -266653,8 +268023,7 @@ class HalfEdge {
|
|
|
266653
268023
|
* * If the edge is horizontal with (approximate) identical y, return the node.
|
|
266654
268024
|
* * If the edge is horizontal with different y, return undefined.
|
|
266655
268025
|
* * If the edge is not horizontal, return the fractional position (possibly outside 0..1) of the intersection.
|
|
266656
|
-
* @param
|
|
266657
|
-
* @param result optional preallocated result
|
|
268026
|
+
* @param node0 Base node of edge
|
|
266658
268027
|
*/
|
|
266659
268028
|
static horizontalScanFraction(node0, y) {
|
|
266660
268029
|
const node1 = node0.faceSuccessor;
|
|
@@ -266669,8 +268038,7 @@ class HalfEdge {
|
|
|
266669
268038
|
* * Compute fractional coordinates of the intersection of a horizontal line with an edge.
|
|
266670
268039
|
* * If the edge is horizontal return undefined (no test for horizontal at y!!!)
|
|
266671
268040
|
* * If the edge is not horizontal and y is between its end y's, return the fraction
|
|
266672
|
-
* @param
|
|
266673
|
-
* @param result optional preallocated result
|
|
268041
|
+
* @param node0 Base node of edge
|
|
266674
268042
|
*/
|
|
266675
268043
|
static horizontalScanFraction01(node0, y) {
|
|
266676
268044
|
const node1 = node0.faceSuccessor;
|
|
@@ -266684,6 +268052,31 @@ class HalfEdge {
|
|
|
266684
268052
|
return fraction;
|
|
266685
268053
|
return undefined;
|
|
266686
268054
|
}
|
|
268055
|
+
/**
|
|
268056
|
+
* Copy various data from source to this.
|
|
268057
|
+
* @param source other half edge.
|
|
268058
|
+
* @param XYZ copy simple coordinates
|
|
268059
|
+
* @param copyVertexData true to copy data belonging to the vertex. (i.e. the "i" member)
|
|
268060
|
+
* @param copyVertexData true to copy data belonging to the edge. (i.e. call transferEdgeData)
|
|
268061
|
+
* @param copyFaceData true to copy faceTag
|
|
268062
|
+
*/
|
|
268063
|
+
copyDataFrom(source, copyXYZ, copyVertexData, copyEdgeData, copyFaceData) {
|
|
268064
|
+
if (copyXYZ) {
|
|
268065
|
+
this.x = source.x;
|
|
268066
|
+
this.y = source.y;
|
|
268067
|
+
this.z = source.z;
|
|
268068
|
+
}
|
|
268069
|
+
if (copyVertexData) {
|
|
268070
|
+
this.i = source.i;
|
|
268071
|
+
}
|
|
268072
|
+
if (copyEdgeData) {
|
|
268073
|
+
HalfEdge.transferEdgeProperties(source, this);
|
|
268074
|
+
this.edgeTag = source.edgeTag;
|
|
268075
|
+
}
|
|
268076
|
+
if (copyFaceData) {
|
|
268077
|
+
this.faceTag = source.faceTag;
|
|
268078
|
+
}
|
|
268079
|
+
}
|
|
266687
268080
|
}
|
|
266688
268081
|
HalfEdge._edgePropertyMasks = [HalfEdgeMask.BOUNDARY_EDGE, HalfEdgeMask.EXTERIOR, HalfEdgeMask.PRIMARY_EDGE, HalfEdgeMask.NULL_FACE];
|
|
266689
268082
|
HalfEdge._totalNodesCreated = 0;
|
|
@@ -266697,7 +268090,7 @@ class HalfEdgeGraph {
|
|
|
266697
268090
|
constructor() {
|
|
266698
268091
|
this._numNodesCreated = 0;
|
|
266699
268092
|
this.allHalfEdges = [];
|
|
266700
|
-
this._maskManager =
|
|
268093
|
+
this._maskManager = _MaskManager__WEBPACK_IMPORTED_MODULE_5__.MaskManager.create(HalfEdgeMask.ALL_GRAB_DROP_MASKS);
|
|
266701
268094
|
}
|
|
266702
268095
|
/** Ask for a mask (from the graph's free pool.) for caller's use.
|
|
266703
268096
|
* * Optionally clear the mask throughout the graph.
|
|
@@ -266724,6 +268117,19 @@ class HalfEdgeGraph {
|
|
|
266724
268117
|
const a = HalfEdge.createHalfEdgePairWithCoordinates(xA, yA, zA, iA, xB, yB, zB, iB, this.allHalfEdges);
|
|
266725
268118
|
return a;
|
|
266726
268119
|
}
|
|
268120
|
+
/**
|
|
268121
|
+
* * Create 2 half edges forming 2 vertices, 1 edge, and 1 face
|
|
268122
|
+
* * The two edges are joined as edgeMate pair.
|
|
268123
|
+
* * The two edges are a 2-half-edge face loop in both the faceSuccessor and facePredecessor directions.
|
|
268124
|
+
* * The two edges are added to the graph's HalfEdge set
|
|
268125
|
+
* * Coordinates are set to zero.
|
|
268126
|
+
* * ids are installed in the two half edges.
|
|
268127
|
+
* @returns Return pointer to the first half edge created. (This has idA as its id.)
|
|
268128
|
+
*/
|
|
268129
|
+
createEdgeIdId(iA = 0, iB = 0) {
|
|
268130
|
+
const a = HalfEdge.createHalfEdgePairWithCoordinates(0.0, 0.0, 0.0, iA, 0.0, 0.0, 0.0, iB, this.allHalfEdges);
|
|
268131
|
+
return a;
|
|
268132
|
+
}
|
|
266727
268133
|
/**
|
|
266728
268134
|
* * create an edge from coordinates x,y,z to (the tail of) an existing half edge.
|
|
266729
268135
|
* @returns Return pointer to the half edge with tail at x,y,z
|
|
@@ -266768,6 +268174,20 @@ class HalfEdgeGraph {
|
|
|
266768
268174
|
const he = HalfEdge.splitEdge(base, xA, yA, zA, iA, this.allHalfEdges);
|
|
266769
268175
|
return he;
|
|
266770
268176
|
}
|
|
268177
|
+
/**
|
|
268178
|
+
* * Create a sliver face "within" an edge.
|
|
268179
|
+
* * this creates two half edges.
|
|
268180
|
+
* * The existing edges both stay in their same face loops and retain coordinates and i value.
|
|
268181
|
+
* * Each existing edge's mate is a new edge (rather than original mate)
|
|
268182
|
+
* * Coordinates are copied to the new edges at respective vertices.
|
|
268183
|
+
* * New faceTag and edgeTag undefined.
|
|
268184
|
+
* * i members are copied around their respective vertices.
|
|
268185
|
+
* @returns Returns the reference to the half edge created.
|
|
268186
|
+
*/
|
|
268187
|
+
splitEdgeCreateSliverFace(base) {
|
|
268188
|
+
const he = HalfEdge.splitEdgeCreateSliverFace(base, this.allHalfEdges);
|
|
268189
|
+
return he;
|
|
268190
|
+
}
|
|
266771
268191
|
/**
|
|
266772
268192
|
* * Insert a vertex in the edge beginning at base, with coordinates specified as a fraction along the existing edge.
|
|
266773
268193
|
* * this creates two half edges.
|
|
@@ -266836,7 +268256,7 @@ class HalfEdgeGraph {
|
|
|
266836
268256
|
const segments = [];
|
|
266837
268257
|
for (const node of this.allHalfEdges) {
|
|
266838
268258
|
if (node.id < node.edgeMate.id)
|
|
266839
|
-
segments.push(
|
|
268259
|
+
segments.push(_curve_LineSegment3d__WEBPACK_IMPORTED_MODULE_6__.LineSegment3d.create(_geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(node.x, node.y), _geometry3d_Point3dVector3d__WEBPACK_IMPORTED_MODULE_1__.Point3d.create(node.faceSuccessor.x, node.faceSuccessor.y)));
|
|
266840
268260
|
}
|
|
266841
268261
|
return segments;
|
|
266842
268262
|
}
|
|
@@ -266905,6 +268325,26 @@ class HalfEdgeGraph {
|
|
|
266905
268325
|
break;
|
|
266906
268326
|
}
|
|
266907
268327
|
}
|
|
268328
|
+
/**
|
|
268329
|
+
* * Visit each edge of the graph once.
|
|
268330
|
+
* * Call the announceEdge function.
|
|
268331
|
+
* * the edge mate will NOT appear in an announceEdge call.
|
|
268332
|
+
* * continue search if announceEdge(graph, node) returns true
|
|
268333
|
+
* * terminate search if announceEdge (graph, node) returns false
|
|
268334
|
+
* @param announceEdge function to apply at one node of each edge.
|
|
268335
|
+
*/
|
|
268336
|
+
announceEdges(announceEdge) {
|
|
268337
|
+
this.clearMask(HalfEdgeMask.VISITED);
|
|
268338
|
+
for (const node of this.allHalfEdges) {
|
|
268339
|
+
if (node.getMask(HalfEdgeMask.VISITED))
|
|
268340
|
+
continue;
|
|
268341
|
+
const mate = node.edgeMate;
|
|
268342
|
+
node.setMask(HalfEdgeMask.VISITED);
|
|
268343
|
+
mate.setMask(HalfEdgeMask.VISITED);
|
|
268344
|
+
if (!announceEdge(this, node))
|
|
268345
|
+
break;
|
|
268346
|
+
}
|
|
268347
|
+
}
|
|
266908
268348
|
/**
|
|
266909
268349
|
* * Visit each vertex loop of the graph once.
|
|
266910
268350
|
* * Call the announceVertex function
|
|
@@ -266923,8 +268363,8 @@ class HalfEdgeGraph {
|
|
|
266923
268363
|
}
|
|
266924
268364
|
}
|
|
266925
268365
|
/**
|
|
266926
|
-
* * Visit each
|
|
266927
|
-
* * Call the
|
|
268366
|
+
* * Visit each half edge (node) of the graph once.
|
|
268367
|
+
* * Call the announceNode function
|
|
266928
268368
|
* * continue search if announceNode(graph, node) returns true
|
|
266929
268369
|
* * terminate search if announce face (graph, node) returns false
|
|
266930
268370
|
* @param announceNode function to apply at one node of each face.
|
|
@@ -266983,6 +268423,99 @@ class HalfEdgeGraph {
|
|
|
266983
268423
|
}
|
|
266984
268424
|
|
|
266985
268425
|
|
|
268426
|
+
/***/ }),
|
|
268427
|
+
|
|
268428
|
+
/***/ "../../core/geometry/lib/esm/topology/HalfEdgeGraphFromIndexedLoopsContext.js":
|
|
268429
|
+
/*!************************************************************************************!*\
|
|
268430
|
+
!*** ../../core/geometry/lib/esm/topology/HalfEdgeGraphFromIndexedLoopsContext.js ***!
|
|
268431
|
+
\************************************************************************************/
|
|
268432
|
+
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
268433
|
+
|
|
268434
|
+
"use strict";
|
|
268435
|
+
__webpack_require__.r(__webpack_exports__);
|
|
268436
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
268437
|
+
/* harmony export */ "HalfEdgeGraphFromIndexedLoopsContext": () => (/* binding */ HalfEdgeGraphFromIndexedLoopsContext)
|
|
268438
|
+
/* harmony export */ });
|
|
268439
|
+
/* harmony import */ var _Graph__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Graph */ "../../core/geometry/lib/esm/topology/Graph.js");
|
|
268440
|
+
/*---------------------------------------------------------------------------------------------
|
|
268441
|
+
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
268442
|
+
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
268443
|
+
*--------------------------------------------------------------------------------------------*/
|
|
268444
|
+
|
|
268445
|
+
/** @packageDocumentation
|
|
268446
|
+
* @module Topology
|
|
268447
|
+
*/
|
|
268448
|
+
/**
|
|
268449
|
+
* Context for building a half edge graph from loops defined only by indices.
|
|
268450
|
+
* * Direct use case:
|
|
268451
|
+
* * Create the context.
|
|
268452
|
+
* * Repeatedly call insertLoop(indicesAroundLoop) to announce various loops.
|
|
268453
|
+
* * Finish by accessing the graph property.
|
|
268454
|
+
* @internal
|
|
268455
|
+
*/
|
|
268456
|
+
class HalfEdgeGraphFromIndexedLoopsContext {
|
|
268457
|
+
constructor() {
|
|
268458
|
+
this._unmatchedEdges = new Map();
|
|
268459
|
+
this._graph = new _Graph__WEBPACK_IMPORTED_MODULE_0__.HalfEdgeGraph();
|
|
268460
|
+
this._halfEdgesAroundCurrentLoop = [];
|
|
268461
|
+
}
|
|
268462
|
+
get graph() { return this._graph; }
|
|
268463
|
+
indexPairToString(index0, index1) {
|
|
268464
|
+
return `${index0.toString()},${index1.toString()}`;
|
|
268465
|
+
}
|
|
268466
|
+
/** Create a loop with specified indices at its vertices.
|
|
268467
|
+
* * For an edge with index pair [indexA, indexB]:
|
|
268468
|
+
* * if [indexB, indexA] has never appeared, a HalfEdge mated pair is created.
|
|
268469
|
+
* * One of that mated pair becomes a HalfEdge in this loop.
|
|
268470
|
+
* * The other is "unmatched"
|
|
268471
|
+
* * When announceMatedHalfEdges(halfEdge) is called:
|
|
268472
|
+
* * halfEdge and its mate are "new"
|
|
268473
|
+
* * all coordinates are zeros.
|
|
268474
|
+
* * each contains (as its halfEdge.id property) one index of the [indexA,indexB] pair.
|
|
268475
|
+
* * those coordinates and indices will never be referenced again by this construction sequence -- the caller is free to mutate them as needed.
|
|
268476
|
+
* * if [indexB, indexA] appeared previously (and its outer HalfEdge was left "unmatched"),
|
|
268477
|
+
* the "unmatched" HalfEdge is used in the loop being constructed.
|
|
268478
|
+
* @param indices Array of indices around the edge. This is accessed cyclically.
|
|
268479
|
+
* @param announceMatedHalfEdges optional function to be called as mated pairs are created. At the call,
|
|
268480
|
+
* the given HalfEdge and its mate will have a pair of successive indices from the array.
|
|
268481
|
+
*/
|
|
268482
|
+
insertLoop(indices, announceMatedHalfEdges) {
|
|
268483
|
+
const n = indices.length;
|
|
268484
|
+
if (n > 1) {
|
|
268485
|
+
let index0 = indices[indices.length - 1];
|
|
268486
|
+
this._halfEdgesAroundCurrentLoop.length = 0;
|
|
268487
|
+
for (const index1 of indices) {
|
|
268488
|
+
const insideString = this.indexPairToString(index0, index1);
|
|
268489
|
+
const halfEdgePreviouslyConstructedFromOppositeSide = this._unmatchedEdges.get(insideString);
|
|
268490
|
+
if (halfEdgePreviouslyConstructedFromOppositeSide === undefined) {
|
|
268491
|
+
// This is the first appearance of this edge in either direction.
|
|
268492
|
+
const outsideString = this.indexPairToString(index1, index0); // string referencing the "other" side of the new edge.
|
|
268493
|
+
const newHalfEdgeAroundLoop = this._graph.createEdgeIdId(index0, index1);
|
|
268494
|
+
if (announceMatedHalfEdges !== undefined)
|
|
268495
|
+
announceMatedHalfEdges(newHalfEdgeAroundLoop);
|
|
268496
|
+
this._unmatchedEdges.set(outsideString, newHalfEdgeAroundLoop.edgeMate);
|
|
268497
|
+
this._halfEdgesAroundCurrentLoop.push(newHalfEdgeAroundLoop);
|
|
268498
|
+
newHalfEdgeAroundLoop.edgeMate.setMask(_Graph__WEBPACK_IMPORTED_MODULE_0__.HalfEdgeMask.EXTERIOR);
|
|
268499
|
+
}
|
|
268500
|
+
else {
|
|
268501
|
+
this._halfEdgesAroundCurrentLoop.push(halfEdgePreviouslyConstructedFromOppositeSide);
|
|
268502
|
+
halfEdgePreviouslyConstructedFromOppositeSide.clearMask(_Graph__WEBPACK_IMPORTED_MODULE_0__.HalfEdgeMask.EXTERIOR);
|
|
268503
|
+
}
|
|
268504
|
+
index0 = index1;
|
|
268505
|
+
}
|
|
268506
|
+
let halfEdgeA = this._halfEdgesAroundCurrentLoop[this._halfEdgesAroundCurrentLoop.length - 1];
|
|
268507
|
+
for (const halfEdgeB of this._halfEdgesAroundCurrentLoop) {
|
|
268508
|
+
const halfEdgeC = halfEdgeA.faceSuccessor;
|
|
268509
|
+
_Graph__WEBPACK_IMPORTED_MODULE_0__.HalfEdge.pinch(halfEdgeB, halfEdgeC);
|
|
268510
|
+
halfEdgeA = halfEdgeB;
|
|
268511
|
+
}
|
|
268512
|
+
return this._halfEdgesAroundCurrentLoop[0];
|
|
268513
|
+
}
|
|
268514
|
+
return undefined;
|
|
268515
|
+
}
|
|
268516
|
+
}
|
|
268517
|
+
|
|
268518
|
+
|
|
266986
268519
|
/***/ }),
|
|
266987
268520
|
|
|
266988
268521
|
/***/ "../../core/geometry/lib/esm/topology/HalfEdgeGraphSearch.js":
|
|
@@ -290811,7 +292344,6 @@ class Capabilities {
|
|
|
290811
292344
|
this._maxVertUniformVectors = 0;
|
|
290812
292345
|
this._maxVaryingVectors = 0;
|
|
290813
292346
|
this._maxFragUniformVectors = 0;
|
|
290814
|
-
this._canRenderDepthWithoutColor = false;
|
|
290815
292347
|
this._maxAntialiasSamples = 1;
|
|
290816
292348
|
this._supportsCreateImageBitmap = false;
|
|
290817
292349
|
this._maxTexSizeAllow = maxTexSizeAllowed;
|
|
@@ -290854,7 +292386,6 @@ class Capabilities {
|
|
|
290854
292386
|
get supportsStandardDerivatives() { return this._isWebGL2 || this.queryExtensionObject("OES_standard_derivatives") !== undefined; }
|
|
290855
292387
|
get supportsMRTTransparency() { return this.maxColorAttachments >= 2; }
|
|
290856
292388
|
get supportsMRTPickShaders() { return this.maxColorAttachments >= 3; }
|
|
290857
|
-
get canRenderDepthWithoutColor() { return this._canRenderDepthWithoutColor; }
|
|
290858
292389
|
get supportsShadowMaps() {
|
|
290859
292390
|
return this.supportsTextureFloat || this.supportsTextureHalfFloat;
|
|
290860
292391
|
}
|
|
@@ -290985,7 +292516,6 @@ class Capabilities {
|
|
|
290985
292516
|
// Determine the maximum depth attachment type.
|
|
290986
292517
|
// this._maxDepthType = this.queryExtensionObject("WEBGL_depth_texture") !== undefined ? DepthType.TextureUnsignedInt32 : DepthType.RenderBufferUnsignedShort16;
|
|
290987
292518
|
this._maxDepthType = this._isWebGL2 || this.queryExtensionObject("WEBGL_depth_texture") !== undefined ? DepthType.TextureUnsignedInt24Stencil8 : DepthType.RenderBufferUnsignedShort16;
|
|
290988
|
-
this._canRenderDepthWithoutColor = this._maxDepthType === DepthType.TextureUnsignedInt24Stencil8 ? this.isDepthRenderableWithoutColor(gl) : false;
|
|
290989
292519
|
this._presentFeatures = this._gatherFeatures();
|
|
290990
292520
|
const missingRequiredFeatures = this._findMissingFeatures(Capabilities.requiredFeatures);
|
|
290991
292521
|
const missingOptionalFeatures = this._findMissingFeatures(Capabilities.optionalFeatures);
|
|
@@ -291030,24 +292560,6 @@ class Capabilities {
|
|
|
291030
292560
|
gl.getError(); // clear any errors
|
|
291031
292561
|
return fbStatus === gl.FRAMEBUFFER_COMPLETE;
|
|
291032
292562
|
}
|
|
291033
|
-
/** Determines if depth textures can be rendered without also having a color attachment bound on the host system. */
|
|
291034
|
-
isDepthRenderableWithoutColor(gl) {
|
|
291035
|
-
const dtExt = this.queryExtensionObject("WEBGL_depth_texture");
|
|
291036
|
-
if (dtExt === undefined)
|
|
291037
|
-
return false;
|
|
291038
|
-
const tex = gl.createTexture();
|
|
291039
|
-
gl.bindTexture(gl.TEXTURE_2D, tex);
|
|
291040
|
-
gl.texImage2D(gl.TEXTURE_2D, 0, gl.DEPTH_STENCIL, 1, 1, 0, gl.DEPTH_STENCIL, dtExt.UNSIGNED_INT_24_8_WEBGL, null);
|
|
291041
|
-
const fb = gl.createFramebuffer();
|
|
291042
|
-
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
|
|
291043
|
-
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.TEXTURE_2D, tex, 0);
|
|
291044
|
-
const fbStatus = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
|
|
291045
|
-
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
291046
|
-
gl.deleteFramebuffer(fb);
|
|
291047
|
-
gl.deleteTexture(tex);
|
|
291048
|
-
gl.getError(); // clear any errors
|
|
291049
|
-
return fbStatus === gl.FRAMEBUFFER_COMPLETE;
|
|
291050
|
-
}
|
|
291051
292563
|
setMaxAnisotropy(desiredMax, gl) {
|
|
291052
292564
|
const ext = this.queryExtensionObject("EXT_texture_filter_anisotropic");
|
|
291053
292565
|
if (undefined === ext)
|
|
@@ -301936,7 +303448,7 @@ module.exports = JSON.parse('{"name":"axios","version":"0.21.4","description":"P
|
|
|
301936
303448
|
/***/ ((module) => {
|
|
301937
303449
|
|
|
301938
303450
|
"use strict";
|
|
301939
|
-
module.exports = JSON.parse('{"name":"@itwin/core-frontend","version":"4.0.0-dev.
|
|
303451
|
+
module.exports = JSON.parse('{"name":"@itwin/core-frontend","version":"4.0.0-dev.7","description":"iTwin.js frontend components","main":"lib/cjs/core-frontend.js","module":"lib/esm/core-frontend.js","typings":"lib/cjs/core-frontend","license":"MIT","scripts":{"build":"npm run -s copy:public && npm run -s build:cjs","build:ci":"npm run -s build && npm run -s build:esm","build:cjs":"npm run -s copy:js:cjs && tsc 1>&2 --outDir lib/cjs","build:esm":"npm run -s copy:js:esm && tsc 1>&2 --module ES2020 --outDir lib/esm","clean":"rimraf lib .rush/temp/package-deps*.json","copy:public":"cpx \\"./src/public/**/*\\" ./lib/public","copy:js:cjs":"cpx \\"./src/**/*.js\\" ./lib/cjs","copy:js:esm":"cpx \\"./src/**/*.js\\" ./lib/esm","docs":"betools docs --includes=../../generated-docs/extract --json=../../generated-docs/core/core-frontend/file.json --tsIndexFile=./core-frontend.ts --onlyJson --excludes=webgl/**/*,**/primitives,**/map/*.d.ts,**/tile/*.d.ts,**/*-css.ts","extract-api":"betools extract-api --entry=core-frontend && npm run extract-extension-api","extract-extension-api":"eslint --no-eslintrc -c \\"../../tools/eslint-plugin/dist/configs/extension-exports-config.js\\" \\"./src/**/*.ts\\" 1>&2","lint":"eslint -f visualstudio \\"./src/**/*.ts\\" 1>&2","pseudolocalize":"betools pseudolocalize --englishDir ./src/public/locales/en --out ./public/locales/en-PSEUDO","test":"npm run -s webpackTests && certa -r chrome","cover":"npm -s test","test:debug":"certa -r chrome --debug","webpackTests":"webpack --config ./src/test/utils/webpack.config.js 1>&2"},"repository":{"type":"git","url":"https://github.com/iTwin/itwinjs-core/tree/master/core/frontend"},"keywords":["Bentley","BIM","iModel","digital-twin","iTwin"],"author":{"name":"Bentley Systems, Inc.","url":"http://www.bentley.com"},"peerDependencies":{"@itwin/appui-abstract":"workspace:^4.0.0-dev.7","@itwin/core-bentley":"workspace:^4.0.0-dev.7","@itwin/core-common":"workspace:^4.0.0-dev.7","@itwin/core-geometry":"workspace:^4.0.0-dev.7","@itwin/core-orbitgt":"workspace:^4.0.0-dev.7","@itwin/core-quantity":"workspace:^4.0.0-dev.7"},"//devDependencies":["NOTE: All peerDependencies should also be listed as devDependencies since peerDependencies are not considered by npm install","NOTE: All tools used by scripts in this package must be listed as devDependencies"],"devDependencies":{"@itwin/appui-abstract":"workspace:*","@itwin/build-tools":"workspace:*","@itwin/core-bentley":"workspace:*","@itwin/core-common":"workspace:*","@itwin/core-geometry":"workspace:*","@itwin/core-orbitgt":"workspace:*","@itwin/core-quantity":"workspace:*","@itwin/certa":"workspace:*","@itwin/eslint-plugin":"workspace:*","@itwin/webgl-compatibility":"workspace:*","@types/chai":"4.3.1","@types/chai-as-promised":"^7","@types/deep-assign":"^0.1.0","@types/lodash":"^4.14.0","@types/mocha":"^8.2.2","@types/node":"18.11.5","@types/qs":"^6.5.0","@types/semver":"7.3.10","@types/superagent":"^4.1.14","@types/sinon":"^9.0.0","babel-loader":"~8.2.5","babel-plugin-istanbul":"~6.1.1","chai":"^4.1.2","chai-as-promised":"^7","cpx2":"^3.0.0","eslint":"^7.11.0","glob":"^7.1.2","mocha":"^10.0.0","nyc":"^15.1.0","rimraf":"^3.0.2","sinon":"^9.0.2","source-map-loader":"^4.0.0","typescript":"~4.4.0","webpack":"^5.64.4"},"//dependencies":["NOTE: these dependencies should be only for things that DO NOT APPEAR IN THE API","NOTE: core-frontend should remain UI technology agnostic, so no react/angular dependencies are allowed"],"dependencies":{"@itwin/object-storage-azure":"~1.4.0","@itwin/cloud-agnostic-core":"~1.4.0","@itwin/object-storage-core":"~1.4.0","@itwin/core-i18n":"workspace:*","@itwin/core-telemetry":"workspace:*","@itwin/webgl-compatibility":"workspace:*","@loaders.gl/core":"^3.1.6","@loaders.gl/draco":"^3.1.6","deep-assign":"^2.0.0","fuse.js":"^3.3.0","lodash":"^4.17.10","qs":"^6.5.3","semver":"^7.3.5","superagent":"^7.1.5","wms-capabilities":"0.4.0","reflect-metadata":"0.1.13"},"nyc":{"extends":"./node_modules/@itwin/build-tools/.nycrc"},"eslintConfig":{"plugins":["@itwin"],"extends":"plugin:@itwin/itwinjs-recommended","rules":{"@itwin/no-internal-barrel-imports":["error",{"required-barrel-modules":["./src/tile/internal.ts"]}],"@itwin/public-extension-exports":["error",{"releaseTags":["public","preview"],"outputApiFile":false}]},"overrides":[{"files":["*.test.ts","*.test.tsx","**/test/**/*.ts"],"rules":{"@itwin/no-internal-barrel-imports":"off"}}]}}');
|
|
301940
303452
|
|
|
301941
303453
|
/***/ })
|
|
301942
303454
|
|