UNPKG

@doegis/core

Version:

DOE GIS API

3 lines (1 loc) 15.2 kB
import{_ as e}from"../../../../chunks/tslib.es6.js";import"../../../../geometry.js";import{getFeatureId as t}from"../../../../analysis/featureReferenceUtils.js";import o from"../../../../core/Accessor.js";import{createTask as i}from"../../../../core/asyncUtils.js";import n from"../../../../core/Evented.js";import r from"../../../../core/Handles.js";import{handlesGroup as s,makeHandle as a}from"../../../../core/handleUtils.js";import l from"../../../../core/Logger.js";import{isNone as c,isSome as d,abortMaybe as u,unwrapOr as p,none as h}from"../../../../core/maybe.js";import{ignoreAbortErrors as g}from"../../../../core/promiseUtils.js";import{initial as v}from"../../../../core/reactiveUtils.js";import{property as m}from"../../../../core/accessorSupport/decorators/property.js";import"../../../../core/accessorSupport/ensureType.js";import"../../../../core/arrayUtils.js";import{subclass as f}from"../../../../core/accessorSupport/decorators/subclass.js";import{c as _,i as b,b as y,n as C,g as I,a as T,j as P,w as O}from"../../../../chunks/vec3.js";import{c as S}from"../../../../chunks/vec3f64.js";import{WatchUpdatingTracking as j}from"../../../../core/support/WatchUpdatingTracking.js";import{projectOrLoad as w,projectBoundingRect as R}from"../../../../geometry/projection.js";import{empty as A,containsPointObject as E,intersectsSegment as H}from"../../../../geometry/support/aaBoundingRect.js";import{fromPoints as F,create as L}from"../../../../geometry/support/ray.js";import{zValueInAbsoluteHeightMode as V}from"../../../../support/elevationInfoUtils.js";import{LineOfSightAnalysisResult as D}from"../LineOfSightAnalysisResult.js";import{LineOfSightComputation as x}from"./LineOfSightComputation.js";import{LineOfSightRayIntersector as N}from"./LineOfSightRayIntersector.js";import{logFailedGeometryProjectionError as k}from"../support/projectionUtils.js";import{StoreResults as G}from"../../webgl-engine/lib/IntersectorInterfaces.js";import{toGraphic as z,hasLod as U,getIntersectedFeatureBSRadius as M}from"../../webgl-engine/lib/intersectorUtilsConversions.js";import{ImmediateTask as Z,TaskPriority as q}from"../../../support/Scheduler.js";import B from"../../../../geometry/Point.js";const W="esri.views.3d.analysis.LineOfSight.LineOfSightController",J=l.getLogger(W);let K=class extends(n.EventedMixin(o)){constructor(e){super(e),this.updateOnCameraChange=!0,this._observerGroundOffsetRenderSpace=0,this._effectiveObserverElevationMode="absolute-height",this._observerFeatureId=null,this._updatingHandles=new j,this._frameTask=Z,this._handles=new r,this._computationHandles=new r,this._externalObserverUpdate=!0}initialize(){const e=this.view.resourceController?.scheduler;this._frameTask=e?e.registerTask(q.LINE_OF_SIGHT_TOOL):Z,this._intersector=new N({view:this.view}),this._handles.add([this._connectObserver(),this._connectComputations(),this._connectTargets()])}destroy(){this._handles.destroy(),this._computationHandles.destroy(),this._computations.removeAll(),this._updatingHandles.destroy()}get updating(){return this._frameTask.updating||this._updatingHandles.updating}get priority(){return this._frameTask.priority}set priority(e){this._frameTask.priority=e}get _computations(){return this.analysisViewData.computations}get _elevationAlignedObserverPositionRenderSpace(){return this.analysisViewData.observerEngineLocation}set _elevationAlignedObserverPositionRenderSpace(e){this.analysisViewData.observerEngineLocation=e}get _screenPixelSize(){return this.view.state.camera.computeScreenPixelSizeAt(this._elevationAlignedObserverPositionRenderSpace)}_computeResult(e){const t=e.computation,{inputPoints:o,computationResult:i}=t,{observerAdjusted:n,targetAdjusted:r}=o,{start:s,end:a}=i;_(s,n),_(a,r);this._canCompute(t)?this._computeIntersection(e):this._interpolateIntersection(e),t.notifyResultChanged(),this.emit("result-changed",{target:e.computation.target,result:t.result})}_updateAdjustedPointsFromFeatures(e){const o=this.view,{sceneIntersectionHelper:i}=o,{inputPoints:n}=e,{observerAdjusted:r,observerFeatureId:s,targetFeatureId:a,targetAdjusted:l}=n;if(c(s)&&c(a))return;const u=b(r,l),p=this._intersector.intersector,h=F(n.observer,n.target,Y);p.options.store=G.ALL,i.intersectToolIntersectorRay(h,p);let g=null,v=null,m=null,f=null;for(const _ of p.results.all){const e=z(_,this.view);if(c(e)||c(_.distanceInRenderSpace))continue;const i=t(e);c(i)||(d(s)&&i===s&&(c(g)&&(g=this._getFeatureDistanceThreshold(_,o,u)),_.distanceInRenderSpace<g&&(m=_)),d(a)&&i===a&&(c(v)&&(v=this._getFeatureDistanceThreshold(_,o,u)),c(f)&&_.distanceInRenderSpace<u&&u-_.distanceInRenderSpace<v&&(f=_)))}d(m)&&m.getIntersectionPoint(r)&&(n.observerSurfaceNormal=m.getTransformedNormal(S())),d(f)&&f.getIntersectionPoint(l)&&(n.targetSurfaceNormal=f.getTransformedNormal(S()))}_getFeatureDistanceThreshold(e,t,o){if(U(e)){const i=M(e,t);if(d(i))return Math.min(i*ee,o)}return 1e-5*o}_adjustStartEndPositions(e){const t=this._screenPixelSize,o=this.view,{inputPoints:i}=e,{observer:n,observerSurfaceNormal:r,target:s,targetSurfaceNormal:a,observerAdjusted:l,targetAdjusted:c}=i,u=X;_(l,n),_(c,s),this._updateAdjustedPointsFromFeatures(e),d(r)?_(u,r):y(u,c,l);const p=t;C(u,u),I(u,u,Math.min(p,1)),T(l,l,u),d(a)?_(u,a):y(u,l,c);const h=o.state.camera.computeScreenPixelSizeAt(c);C(u,u),I(u,u,Math.min(h,1)),T(c,c,u)}_computeIntersection({computation:e,interpolationInfo:t}){const{view:o}=this,{sceneIntersectionHelper:i,renderCoordsHelper:n}=o;if(c(i))return;const r=this._intersector.intersector,{computationResult:s,inputPoints:a}=e,{observer:l,target:u}=a,{start:p,end:h}=s,g=F(p,h,Y);r.options.store=G.MIN,i.intersectToolIntersectorRay(g,r);const v=r.results.min,m=s.intersection,f=X;let b=!0;if(d(v)&&v.getIntersectionPoint(m)){_(t.originalIntersection,m),_(t.originalObserver,p),_(t.originalTarget,h),n.fromRenderCoords(m,f,o.spatialReference);const e=1-P(h,u)/P(p,u);b=P(l,m)>=e*P(l,u)}const y=new B(f,o.spatialReference);{const{result:t,target:i}=e;d(t)?(t.target=i,t.intersectedGraphic=b?null:z(v,o),t.intersectedLocation=b?null:y,t.visible=b):e.result=new D({target:i,elevationAlignedTargetLocation:e.elevationAlignedTargetLocation,intersectedGraphic:b?null:z(v,o),intersectedLocation:b?null:y,visible:b})}s.isValid=a.isValid=!0,s.isTargetVisible=b}_interpolateIntersection({computation:e,interpolationInfo:t}){const{computationResult:o,inputPoints:i}=e,{start:n,end:r,intersection:s}=o,{originalIntersection:a,originalObserver:l,originalTarget:c}=t;if(_(s,a),i.isValid){const e=X,t=P(l,a)/P(l,c);O(e,n,l),I(e,e,1-t),T(s,s,e),O(e,r,c),I(e,e,t),T(s,s,e),o.isValid=!0}else e.result=null,o.isValid=!1,o.isTargetVisible=!1}_canCompute(e){const t=this.analysisViewData.elevationAlignedObserver,o=this.view.frustum;if(c(t)||c(e.elevationAlignedTargetLocation)||c(o))return!1;const{observerAdjusted:i,targetAdjusted:n}=e.inputPoints,r=o.intersectsPoint(i),s=o.intersectsPoint(n);return r&&s}_onObserverPositionChange(e,o,i,n,r){if(this._externalObserverUpdate=r,c(e))return this.analysisViewData.elevationAlignedObserver=null,void(this._observerFeatureId=null);if(c(o))return k(this.analysis,e.spatialReference,J),void(this.analysisViewData.elevationAlignedObserver=null);const s=this._getEffectiveElevationInfo(o,i),{absoluteZ:a,elevation:l}=V(o.x,o.y,o.z,this.view.spatialReference,this.view,s),d=o.clone();d.z=a,this._effectiveObserverElevationMode=s.mode,this.analysisViewData.elevationAlignedObserver=d;const u=S();this.view.renderCoordsHelper.toRenderCoords(d,u),this._elevationAlignedObserverPositionRenderSpace=u,this._observerGroundOffsetRenderSpace=a-l,this._observerFeatureId=t(n),this.priority=q.LINE_OF_SIGHT_TOOL_INTERACTIVE}_onObserverRenderSpacePositionChangeForComputation(e,t,o,i,n){const{inputPoints:r}=e;switch(_(r.observer,t),r.observerFeatureId=n,r.observerSurfaceNormal=null,i){case"on-the-ground":case"relative-to-ground":{const e=this._intersector.updateFromGroundIntersection(r.observer,o,r.observer);c(r.observerFeatureId)&&(r.observerSurfaceNormal=e)}}this._adjustStartEndPositions(e),e.notifyInputPointsChanged(),this.priority=q.LINE_OF_SIGHT_TOOL_INTERACTIVE}_onTargetPositionChange(e,o,i,n,r,s=!0){const a=e.inputPoints;if(s&&(a.isValid=!1),c(i))return d(o)&&k(this.analysis,o.spatialReference,J),e.elevationAlignedTargetLocation=null,void e.notifyInputPointsChanged();const l=this._getEffectiveElevationInfo(i,n),{absoluteZ:u,elevation:p}=V(i.x,i.y,i.z,this.view.spatialReference,this.view,l),h=i.clone();switch(h.z=u,e.elevationAlignedTargetLocation=h,this.view.renderCoordsHelper.toRenderCoords(e.elevationAlignedTargetLocation,a.target),a.targetFeatureId=t(r),a.targetSurfaceNormal=null,l.mode){case"on-the-ground":case"relative-to-ground":{const e=this._intersector.updateFromGroundIntersection(a.target,u-p,a.target);c(a.targetFeatureId)&&(a.targetSurfaceNormal=e)}}this._adjustStartEndPositions(e),e.notifyInputPointsChanged(),this.priority=q.LINE_OF_SIGHT_TOOL_INTERACTIVE}_connectComputationToTarget(e){return s([this._updatingHandles.add((()=>({computation:e,targetPosition:e.target.position,targetElevationInfo:e.target.elevationInfo,targetFeatureInfo:e.target.feature,projectedTargetPosition:w(e.target.position,this.view.spatialReference)})),(({computation:e,targetPosition:t,targetElevationInfo:o,targetFeatureInfo:i,projectedTargetPosition:n})=>{d(n.pending)?this._updatingHandles.addPromise(n.pending):this._onTargetPositionChange(e,t,n.geometry,o,i)}),v)])}_connectComputationToObserver(e){return this._updatingHandles.add((()=>({computation:e,observer:this.analysisViewData.elevationAlignedObserver})),(({computation:e})=>{this._externalObserverUpdate&&(e.inputPoints.isValid=!1,e.notifyInputPointsChanged())}),v)}_connectComputationToRenderSpaceObserver(e){return this._updatingHandles.add((()=>({computation:e,observer:this._elevationAlignedObserverPositionRenderSpace,observerGroundOffset:this._observerGroundOffsetRenderSpace,observerElevationMode:this._effectiveObserverElevationMode,observerFeatureId:this._observerFeatureId})),(({computation:e,observer:t,observerGroundOffset:o,observerElevationMode:i,observerFeatureId:n})=>{this._onObserverRenderSpacePositionChangeForComputation(e,t,o,i,n)}),v)}_connectComputationToCamera(e){return this._updatingHandles.add((()=>({camera:this.view.state.camera,isDirty:this._isCameraDirty})),(({isDirty:t})=>{!this.updateOnCameraChange||e.inputPoints.isValid&&!t||e.notifyInputPointsChanged()}))}_connectComputationToSlicePlane(e){return this._updatingHandles.add((()=>this.view.slicePlane),(()=>{e.inputPoints.isValid=!1,e.notifyInputPointsChanged()}))}_connectComputationToElevation(e){const t=(o,i)=>{const n=this.analysis.observer,r=e.target;let s=null,a=null,l=null,u=null,p=null,h=null;if(d(n)&&d(n.position)){const e=w(n.position,this.view.spatialReference);if(d(e.pending))return this._updatingHandles.addPromise(e.pending),void e.pending.finally((()=>t(o,i)));s=e.geometry,a=n.elevationInfo,l=n.feature}if(d(r.position)){const e=w(r.position,this.view.spatialReference);if(d(e.pending))return this._updatingHandles.addPromise(e.pending),void e.pending.finally((()=>t(o,i)));u=e.geometry,p=r.elevationInfo,h=r.feature}c(s)&&c(u)||(R(o,i,$,this.view.spatialReference),d(s)&&E($,s)&&this._onObserverPositionChange(d(n)?n.position:null,s,a,l,!1),d(u)&&E($,u)&&this._onTargetPositionChange(e,r.position,u,p,h,!1),d(s)&&d(u)&&H($,s,u)&&e.notifyInputPointsChanged())};return this.view.elevationProvider.on("elevation-change",(e=>t(e.extent,e.spatialReference)))}_connectComputationToTask(e){let t=h;const o={computation:e,interpolationInfo:{originalIntersection:S(),originalObserver:S(),originalTarget:S()}};return s([this._updatingHandles.add((()=>e.inputPoints),(()=>{t=u(t),t=i((async e=>{await g(this._frameTask.schedule((()=>this._computeResult(o)),e))}))}),{initial:!0,equals:()=>!1}),a((()=>t=u(t)))])}_connectComputation(e){const t=this._computationHandles;t.has(e)||t.add([this._connectComputationToTarget(e),this._connectComputationToObserver(e),this._connectComputationToRenderSpaceObserver(e),this._connectComputationToCamera(e),this._connectComputationToSlicePlane(e),this._connectComputationToElevation(e),this._connectComputationToTask(e)],e)}_disconnectComputation(e){this._computationHandles.remove(e)}_onComputationCollectionChange({added:e,removed:t}){for(const o of t)this._disconnectComputation(o);for(const o of e)this._connectComputation(o)}_onTargetCollectionChange({added:e,removed:t}){for(const o of t)this._removeTarget(o);for(const o of e)this._addTarget(o)}_onCursorTargetChange(e,t){d(t)&&this._removeTarget(t),d(e)&&this._addTarget(e)}_addTarget(e){this._computations.some((t=>t.target===e))||this._computations.add(new x({target:e}))}_removeTarget(e){const t=this._computations.findIndex((t=>t.target===e));this._computations.removeAt(t)}_connectObserver(){return s([this._updatingHandles.add((()=>({observerPosition:d(this.analysis.observer)?this.analysis.observer.position:null,projectedObserverPosition:w(d(this.analysis.observer)?this.analysis.observer.position:null,this.view.spatialReference),observerElevationInfo:d(this.analysis.observer)?this.analysis.observer.elevationInfo:null,observerFeatureInfo:d(this.analysis.observer)?this.analysis.observer.feature:null})),(({observerPosition:e,projectedObserverPosition:t,observerElevationInfo:o,observerFeatureInfo:i})=>{d(t.pending)?this._updatingHandles.addPromise(t.pending):this._onObserverPositionChange(e,t.geometry,o,i,!0)}),v)])}_connectComputations(){return this._updatingHandles.addOnCollectionChange((()=>this._computations),(e=>this._onComputationCollectionChange(e)),{initial:!0,final:!0})}_connectTargets(){return s([this._updatingHandles.addOnCollectionChange((()=>this.analysis.targets),(e=>this._onTargetCollectionChange(e)),{initial:!0,final:!0}),this._updatingHandles.add((()=>this.analysisViewData.cursorTarget),((e,t)=>{this._onCursorTargetChange(e,t)}))])}get _isCameraDirty(){const e=this.analysisViewData.elevationAlignedObserver,{view:t}=this,{renderCoordsHelper:o}=t;if(c(e)||c(o))return!1;const i=X;o.toRenderCoords(e,i);const n=t.state.camera.computeScreenPixelSizeAt(i);return Math.abs((n-this._screenPixelSize)/this._screenPixelSize)>Q}_getEffectiveElevationInfo(e,t){return e.hasZ?p(t,{mode:"absolute-height",offset:0}):{mode:"on-the-ground",offset:0}}};e([m({constructOnly:!0})],K.prototype,"analysis",void 0),e([m({constructOnly:!0})],K.prototype,"analysisViewData",void 0),e([m({constructOnly:!0})],K.prototype,"view",void 0),e([m()],K.prototype,"updating",null),e([m()],K.prototype,"priority",null),e([m()],K.prototype,"updateOnCameraChange",void 0),e([m()],K.prototype,"_computations",null),e([m()],K.prototype,"_elevationAlignedObserverPositionRenderSpace",null),e([m()],K.prototype,"_observerGroundOffsetRenderSpace",void 0),e([m()],K.prototype,"_effectiveObserverElevationMode",void 0),e([m()],K.prototype,"_observerFeatureId",void 0),e([m()],K.prototype,"_screenPixelSize",null),e([m({readOnly:!0})],K.prototype,"_updatingHandles",void 0),e([m()],K.prototype,"_frameTask",void 0),e([m()],K.prototype,"_isCameraDirty",null),K=e([f(W)],K);const Q=.1,X=S(),Y=L(),$=A(),ee=.05;export{K as LineOfSightController};