@arcgis/core
Version:
ArcGIS Maps SDK for JavaScript: A complete 2D and 3D mapping and data visualization API
3 lines (2 loc) • 12 kB
JavaScript
/* COPYRIGHT Esri - https://js.arcgis.com/5.0.8/LICENSE.txt */
import{__decorate as e}from"tslib";import{volumeMeasurementConfiguration as t}from"../../../../analysis/VolumeMeasurement/volumeMeasurementConfiguration.js";import r from"../../../../core/Accessor.js";import o from"../../../../core/Logger.js";import{debounce as i}from"../../../../core/promiseUtils.js";import{createVolume as n}from"../../../../core/quantity.js";import{whenOnce as s,watch as a,syncAndInitial as l}from"../../../../core/reactiveUtils.js";import{property as u,subclass as p}from"../../../../core/accessorSupport/decorators.js";import{e as c}from"../../../../chunks/earcut.js";import{create as m}from"../../../../core/libs/gl-matrix-2/factories/mat4f64.js";import{scaleAndAdd as d,sqrDist as h}from"../../../../core/libs/gl-matrix-2/math/vec3.js";import{fromValues as g,clone as f,create as y}from"../../../../core/libs/gl-matrix-2/factories/vec3f64.js";import{UpdatingHandles as _}from"../../../../core/support/UpdatingHandles.js";import v from"../../../../geometry/Multipoint.js";import{projectOrLoad as w}from"../../../../geometry/projectionUtils.js";import{e as b}from"../../../../chunks/containsOperator.js";import{e as j}from"../../../../chunks/convexHullOperator.js";import{e as E}from"../../../../chunks/simplifyOperator.js";import{e as R}from"../../../../chunks/unionOperator.js";import{computeTranslationToOriginAndRotation as C}from"../../../../geometry/projection/computeTranslationToOriginAndRotation.js";import{projectBoundingRect as T}from"../../../../geometry/projection/projectBoundingRect.js";import{fromExtent as G,intersects as L,create as O,empty as x}from"../../../../geometry/support/aaBoundingRect.js";import{newDoubleArray as I}from"../../../../geometry/support/DoubleArray.js";import{t as D}from"../../../../chunks/vec3.js";import H from"../../../../symbols/support/ElevationInfo.js";import{logFailedGeometryProjectionError as M}from"../support/projectionUtils.js";import{VolumeMeasurementCutFillComputation as V}from"./VolumeMeasurementCutFillComputation.js";import{VolumeMeasurementInsufficientDataError as A,VolumeMeasurementPerimeterTooLargeError as P,VolumeMeasurementUnsupportedCoordinateSystemError as U,VolumeMeasurementUnsupportedLayerTransparencyError as k}from"./volumeMeasurementErrors.js";import{VolumeMeasurementRawResult as S}from"./VolumeMeasurementRawResult.js";import F from"./VolumeMeasurementResult.js";import{ElevationContext as W}from"../../layers/graphics/ElevationContext.js";import{getElevationAtPoint as N}from"../../support/ElevationProvider.js";import{polygonToRenderInfo as z}from"../../support/renderInfoUtils/polygon.js";import{IteratorPreorder as q}from"../../terrain/tileUtils.js";import{CutFillDepth as B,TargetGeometryRenderInfo as Z}from"../../webgl-engine/lib/CutFillDepth.js";import{isIntegratedMeshLayerView as J}from"../../../support/layerViewUtils.js";import{MeasurementWorkerHandle as K}from"../../../support/MeasurementWorkerHandle.js";let Q=class extends r{constructor(e){super(e),this._measurementWorkerHandle=new K,this._getElevationProvider=()=>this.view.elevationProvider,this.labelAnchors=null,this._updatingHandles=new _,this._rawResult=null,this._sufficientDataCoverage=!0,this._tileIterator=new q,this._intersectingObbs=[],this._intersectingTiles=[],this._debouncedUpdate=i(async(e,t,r,o)=>{if(!this._renderer.done)return;const{renderCoordsHelper:i}=this.view,n=new V({extent:t,localOrigin:r,renderCoordsHelper:i});this._renderer.update(n,o),this._determineDataCoverage(n);const[a]=await Promise.allSettled([this._measurementWorkerHandle.areaHorizontal(e,{returnLength:!0}),s(()=>this._renderer.done).then(()=>{this._updateLabelAnchors(n,this._renderer.getResults())})]);if(this.error)return void(this._rawResult=null);const l=this._renderer.getResults();this._updateResult(n,l,"fulfilled"===a.status?a.value:null)}),this._determineDataCoverage=e=>{const{elevationAlignedGeometry:t}=this,{frustum:r}=this._renderer,{cameraDimensions:o}=e;t&&r&&(this._intersectingObbs.length=0,this._imLayerViewsAffectingMeasurement.forEach(e=>{this._findIntersectingObbs(e,r)}),this._intersectingObbs.length?this._sufficientDataCoverage=this._sufficientIntegratedMeshCoverage(t,o):(this._findIntersectingTerrainTiles(t),this._sufficientDataCoverage=this._sufficientTerrainCoverage(o)))}}initialize(){const e=this.view;this._renderer=new B({view:e}),this.addHandles([this._createElevationUpdateHandle(),a(()=>({projectedGeometry:this._projectedGeometry,localOrigin:this._localOrigin,targetGeometryRenderInfos:this._targetGeometryRenderInfos}),({projectedGeometry:e,localOrigin:t,targetGeometryRenderInfos:r})=>{const o=e?.extent;if(!(e&&o&&t&&r))return this._rawResult=null,void(this._sufficientDataCoverage=!0);this._updatingHandles.addPromise(this._debouncedUpdate(e,o,t,r))},l)])}destroy(){this._updatingHandles.destroy(),this._renderer.destroy(),this._measurementWorkerHandle.destroy()}get _projectedGeometry(){const e=this.analysis.geometry;if(!e||!this.analysis.valid)return null;const t=E(e),r=w(t,this.view.spatialReference);return r.pending?(this._updatingHandles.addPromise(r.pending),null):(t&&!r.geometry&&M(this.analysis,e.spatialReference,o.getLogger(this)),r.geometry)}get _localOrigin(){const e=this._projectedGeometry?.extent;return e?g(e.center.x,e.center.y,0):null}get elevationAlignedGeometry(){const e=this._projectedGeometry;if(!e)return null;const t=e.clone();return X(this._getElevationProvider(),t),t}get targetGeometry(){const{elevationAlignedGeometry:e}=this;if(!e)return null;const t=this.analysis.measureType,{effectiveTargetElevation:r}=this.analysisViewData;if("stockpile"===t||null==r)return e;const o=e.clone();return o.rings.forEach(e=>e.forEach(e=>e[2]=r)),o}get _targetGeometryRenderInfos(){const e=this.targetGeometry,t=this._projectedGeometry?.extent,r=this._localOrigin;if(!e||!t||!r)return null;const{elevationProvider:o,renderCoordsHelper:i}=this.view,n=z(e,o,i,W.fromElevationInfo(new H({mode:"absolute-height"}))),{polygons:s}=n;return s.map(e=>{const o=c(e.position,e.holeIndices,3),n=I(3*e.count),s=m(),a=m();return C(t.spatialReference,r,s,i.spatialReference),a[12]=-s[12],a[13]=-s[13],a[14]=-s[14],D(n,e.position,a),new Z(n,o)})}get updating(){return this._renderer.updating||this._updatingHandles.updating}get result(){const e=this._rawResult,{volume:t,area:r,length:o}=this.analysisViewData.effectiveDisplayUnits;return e?new F({measureType:this.analysis.measureType,rawResult:e,volumeUnit:t,areaUnit:r,lengthUnit:o}):null}get error(){return this._unsupportedCoordinateSystemError??this._unsupportedLayerTransparencyError??this._perimeterTooLargeError??this._insufficientDataError}get _imLayerViewsAffectingMeasurement(){return this.view.allLayerViews.filter(e=>J(e)).filter(e=>e.visible&&!e.suspended)}get _insufficientDataError(){return this._sufficientDataCoverage?null:new A}get _perimeterTooLargeError(){return this._perimeterTooLargeLocalError??this._perimeterTooLargeGlobalError}get _perimeterTooLargeLocalError(){const{spatialReference:e,state:{isLocal:r}}=this.view;if(!r||!e.isWebMercator)return null;const o=this._perimeter,{maxPerimeterLocalWebMercator:i}=t;return null!=o&&o>i?new P:null}get _perimeterTooLargeGlobalError(){if(!this.view.state.isGlobal)return null;const e=this._perimeter,{maxPerimeterGlobal:r}=t;return null!=e&&e>r?new P:null}get _unsupportedCoordinateSystemError(){return this.view.state.isLocal&&this.view.spatialReference.isGeographic?new U:null}get _unsupportedLayerTransparencyError(){return this.view.map.ground&&this.view.map.ground.opacity<1?new k:null}get _perimeter(){if(!this._targetGeometryRenderInfos)return null;let e=null;for(const t of this._targetGeometryRenderInfos){const r=$(ee(t.positions));e=r?Math.max(e??0,r):e}return null!=e?e/this.view.renderCoordsHelper.unitInMeters:null}_createElevationUpdateHandle(){const e=e=>{const t=this._projectedGeometry?.extent;"ground"===e.context&&t&&(T(e.extent,e.spatialReference,re,this.view.spatialReference),G(t,oe),L(re,oe)&&(this._getElevationProvider=()=>this.view.elevationProvider))};return this.view.elevationProvider.on("elevation-change",t=>e(t))}_updateResult(e,t,r){const{unitInMeters:o}=this.view.renderCoordsHelper,{dimensions:{width:i,height:s},cameraNearFar:{near:a,far:l}}=e,u=i/t.width*(s/t.height),p=Y(t.cut.totalDepth,a,l)*u,c=Y(t.fill.totalDepth,a,l)*u,m=o**3;this._rawResult=new S({cutVolume:n(Math.abs(p*m),"cubic-meters"),fillVolume:n(c*m,"cubic-meters"),area:r?.area,perimeter:r?.length})}_updateLabelAnchors(e,t){const{dimensions:{width:r,height:o},cameraNearFar:{near:i,far:n},cameraPositionRenderSpace:s,northVector:a,eastVector:l,upVector:u}=e,p=e=>{const{labelDepth:p,labelCoords:c,totalDepth:m}=e,h=f(s);return 0!==m&&(d(h,h,l,r*(c[0]/t.width-.5)),d(h,h,a,o*(c[1]/t.height-.5))),d(h,h,u,-Y(p,i,n)),h};this.labelAnchors={cut:p(t.cut),fill:p(t.fill)}}_findIntersectingObbs(e,t){const r=this._intersectingObbs;"integrated-mesh-3d"===e.type&&e.getVisibleNodes().forEach(o=>{e.isNodeLoaded(o.index)&&o.geometryObbInRenderSR?.intersectsFrustum(t)&&r.push(o.geometryObbInRenderSR)}),"integrated-mesh-3dtiles"===e.type&&e.forEachVisibleComponentObject(({obb:e})=>{e.intersectsFrustum(t)&&r.push(e)})}_sufficientIntegratedMeshCoverage(e,t){const{renderCoordsHelper:r,spatialReference:o}=this.view,i=[],n=new v({spatialReference:o});if(this._intersectingObbs.forEach(e=>{if(te(e.radius,t)&&(e.getCorners(ne),n.points.length=0,ne.forEach(e=>{const t=r.fromRenderCoords(e,se,o);t&&n.addPoint([t[0],t[1]])}),n.points.length)){const e=j(n);"polygon"===e?.type&&i.push(e)}}),!i.length)return!1;const s=R(i);return!!s&&b(s,e)}_findIntersectingTerrainTiles(e){const{basemapTerrain:t}=this.view;if(this._intersectingTiles.length=0,!e.extent)return;G(e.extent,ie);const r=this._tileIterator;r.reset(t.rootTiles);for(let o=r.next();o;o=r.next())o.intersectsExtent(ie)?o.rendered&&this._intersectingTiles.push(o):r.skipSubtree()}_sufficientTerrainCoverage(e){const{basemapTerrain:{tilingScheme:t}}=this.view,r=256/t.pixelSize;return this._intersectingTiles.every(t=>te(t.radius*r,e))}};function X(e,t){t.hasZ=!0,t.rings.forEach(t=>t.forEach(t=>t[2]=N(e,t,"ground")??0))}function Y(e,t,r){return e*(r-t)+t}function $(e){if(!e)return null;let t=null,r=null,o=0;for(const i of e)t||(t=[i[0],i[1],i[2]??0]),r?o+=h(r,i):r=[0,0,0],r[0]=i[0],r[1]=i[1],r[2]=i[2];return t&&r&&(o+=h(r,t)),Math.sqrt(o)}function*ee(e){const t=y();for(let r=0;r<e.length;r+=3)t[0]=e[r],t[1]=e[r+1],t[2]=e[r+2],yield t}e([u()],Q.prototype,"_projectedGeometry",null),e([u()],Q.prototype,"_localOrigin",null),e([u()],Q.prototype,"_getElevationProvider",void 0),e([u()],Q.prototype,"elevationAlignedGeometry",null),e([u()],Q.prototype,"targetGeometry",null),e([u()],Q.prototype,"_targetGeometryRenderInfos",null),e([u({constructOnly:!0})],Q.prototype,"analysis",void 0),e([u({constructOnly:!0})],Q.prototype,"analysisViewData",void 0),e([u({constructOnly:!0})],Q.prototype,"view",void 0),e([u()],Q.prototype,"updating",null),e([u()],Q.prototype,"result",null),e([u()],Q.prototype,"labelAnchors",void 0),e([u()],Q.prototype,"error",null),e([u()],Q.prototype,"_imLayerViewsAffectingMeasurement",null),e([u()],Q.prototype,"_insufficientDataError",null),e([u()],Q.prototype,"_perimeterTooLargeError",null),e([u()],Q.prototype,"_perimeterTooLargeLocalError",null),e([u()],Q.prototype,"_perimeterTooLargeGlobalError",null),e([u()],Q.prototype,"_unsupportedCoordinateSystemError",null),e([u()],Q.prototype,"_unsupportedLayerTransparencyError",null),e([u()],Q.prototype,"_perimeter",null),e([u()],Q.prototype,"_renderer",void 0),e([u({readOnly:!0})],Q.prototype,"_updatingHandles",void 0),e([u()],Q.prototype,"_rawResult",void 0),e([u()],Q.prototype,"_sufficientDataCoverage",void 0),Q=e([p("esri.views.3d.analysis.VolumeMeasurement.VolumeMeasurementCutFillController")],Q);const te=(e,t)=>e<(t.width+t.height)/2,re=x(),oe=x(),ie=O(),ne=new Array(8).fill(0).map(()=>y()),se=y();export{Q as VolumeMeasurementCutFillController};