@arcgis/core
Version:
ArcGIS Maps SDK for JavaScript: A complete 2D and 3D mapping and data visualization API
3 lines (2 loc) • 14.2 kB
JavaScript
/* COPYRIGHT Esri - https://js.arcgis.com/5.0.19/LICENSE.txt */
import{__decorate as e}from"tslib";import{updatePointsFromFeatureReference as t,getFeatureId as o}from"../../../../analysis/featureReferenceUtils.js";import{createTask as n}from"../../../../core/asyncUtils.js";import{EventedAccessor as i}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{abortMaybe as u}from"../../../../core/maybe.js";import{ignoreAbortErrors as c}from"../../../../core/promiseUtils.js";import{initial as d,on as p}from"../../../../core/reactiveUtils.js";import{property as g,subclass as h}from"../../../../core/accessorSupport/decorators.js";import{copy as m,subtract as v,normalize as f,scale as _,add as b,dist as y,sub as C}from"../../../../core/libs/gl-matrix-2/math/vec3.js";import{create as T}from"../../../../core/libs/gl-matrix-2/factories/vec3f64.js";import{UpdatingHandles as O}from"../../../../core/support/UpdatingHandles.js";import P from"../../../../geometry/Point.js";import{projectOrLoad as I}from"../../../../geometry/projectionUtils.js";import{projectBoundingRect as S}from"../../../../geometry/projection/projectBoundingRect.js";import{intersectsSegment as w}from"../../../../geometry/support/aaBoundingBox.js";import{containsPointObject as j,intersectsSegment as R,empty as A}from"../../../../geometry/support/aaBoundingRect.js";import{fromPoints as H,create as E}from"../../../../geometry/support/ray.js";import{zValueInAbsoluteHeightMode as L}from"../../../../support/elevationInfoUtils.js";import V from"../LineOfSightAnalysisResult.js";import{LineOfSightComputation as F}from"./LineOfSightComputation.js";import{LineOfSightRayIntersector as x}from"./LineOfSightRayIntersector.js";import{logFailedGeometryProjectionError as D}from"../support/projectionUtils.js";import{toGraphic as G}from"../../webgl-engine/lib/intersectorUtilsConversions.js";import{ImmediateTask as U,TaskPriority as z}from"../../../support/Scheduler.js";let N=class extends i{constructor(e){super(e),this.updateOnCameraChange=!0,this._observerGroundOffsetRenderSpace=0,this._effectiveObserverElevationMode="absolute-height",this._observerFeatureId=null,this._updatingHandles=new O,this._frameTask=U,this._computationHandles=new r,this._externalObserverUpdate=!0}initialize(){const e=this.view.resourceController?.scheduler;this._frameTask=e?e.registerTask(z.LINE_OF_SIGHT_TOOL):U,this._intersector=new x({view:this.view}),this.addHandles([this._connectObserver(),this._connectComputations(),this._connectTargets()])}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:n}=t,{observerAdjusted:i,targetAdjusted:r}=o,{start:s,end:a}=n;m(s,i),m(a,r);this._canCompute(t)?this._computeIntersection(e):M(e),t.notifyResultChanged(),this.emit("result-changed",{target:e.computation.target,result:t.result})}_adjustStartEndPositions(e){const{view:o}=this,{inputPoints:n}=e,{observer:i,target:r,observerAdjusted:s,targetAdjusted:a}=n;m(s,i),m(a,r),t(o,this._intersector.intersector,n);const{observerSurfaceNormal:l,targetSurfaceNormal:u}=n,c=this._screenPixelSize,d=Z;null!=l?m(d,l):v(d,a,s);const p=c;f(d,d),_(d,d,Math.min(p,1)),b(s,s,d),null!=u?m(d,u):v(d,s,a);const g=o.state.camera.computeScreenPixelSizeAt(a);f(d,d),_(d,d,Math.min(g,1)),b(a,a,d)}_computeIntersection({computation:e,interpolationInfo:t}){const{view:o}=this,{sceneIntersectionHelper:n,renderCoordsHelper:i}=o;if(null==n)return;const r=this._intersector.intersector,{computationResult:s,inputPoints:a}=e,{observer:l,target:u}=a,{start:c,end:d}=s,p=H(c,d,q);r.options.store=0,n.intersectToolIntersectorRay(p,r);const g=r.results.min,h=s.intersection,v=Z;let f=!0;if(null!=g&&g.getIntersectionPoint(h)){m(t.originalIntersection,h),m(t.originalObserver,c),m(t.originalTarget,d),i.fromRenderCoords(h,v,o.spatialReference);const e=1-y(d,u)/y(c,u);f=y(l,h)>=e*y(l,u)}const _=new P(v,o.spatialReference);{const{result:t,target:n}=e;null!=t?(t.target=n,t.intersectedGraphic=f?null:G(g,o),t.intersectedLocation=f?null:_,t.visible=f):e.result=new V({target:n,elevationAlignedTargetLocation:e.elevationAlignedTargetLocation,intersectedGraphic:f?null:G(g,o),intersectedLocation:f?null:_,visible:f})}s.isValid=a.isValid=!0,s.isTargetVisible=f}_canCompute(e){const t=this.analysisViewData.elevationAlignedObserver,{frustum:o}=this.view;if(null==t||null==e.elevationAlignedTargetLocation||null==o)return!1;const{observerAdjusted:n,targetAdjusted:i}=e.inputPoints,r=o.intersectsPoint(n),s=o.intersectsPoint(i);return r&&s}_onObserverPositionChange(e,t,n,i,r){if(this._externalObserverUpdate=r,null==e)return this.analysisViewData.elevationAlignedObserver=null,void(this._observerFeatureId=null);if(null==t)return D(this.analysis,e.spatialReference,l.getLogger(this)),void(this.analysisViewData.elevationAlignedObserver=null);const s=k(t,n),{absoluteZ:a,elevation:u}=L(t.x,t.y,t.z,this.view.spatialReference,this.view,s),c=t.clone();c.z=a,this._effectiveObserverElevationMode=s.mode,this.analysisViewData.elevationAlignedObserver=c;const d=T();this.view.renderCoordsHelper.toRenderCoords(c,d),this._elevationAlignedObserverPositionRenderSpace=d,this._observerGroundOffsetRenderSpace=a-u,this._observerFeatureId=o(i),this.priority=z.LINE_OF_SIGHT_TOOL_INTERACTIVE}_onObserverRenderSpacePositionChangeForComputation(e,t,o,n,i){const{inputPoints:r}=e;switch(m(r.observer,t),r.observerFeatureId=i,r.observerSurfaceNormal=null,n){case"on-the-ground":case"relative-to-ground":{const e=this._intersector.updateFromGroundIntersection(r.observer,o,r.observer);null==r.observerFeatureId&&(r.observerSurfaceNormal=e)}}this._adjustStartEndPositions(e),e.notifyInputPointsChanged(),this.priority=z.LINE_OF_SIGHT_TOOL_INTERACTIVE}_onTargetPositionChange(e,t,n,i,r,s=!0){const a=e.inputPoints;if(s&&(a.isValid=!1),null==n)return null!=t&&D(this.analysis,t.spatialReference,l.getLogger(this)),e.elevationAlignedTargetLocation=null,void e.notifyInputPointsChanged();const u=k(n,i),{absoluteZ:c,elevation:d}=L(n.x,n.y,n.z,this.view.spatialReference,this.view,u),p=n.clone();switch(p.z=c,e.elevationAlignedTargetLocation=p,this.view.renderCoordsHelper.toRenderCoords(e.elevationAlignedTargetLocation,a.target),a.targetFeatureId=o(r),a.targetSurfaceNormal=null,u.mode){case"on-the-ground":case"relative-to-ground":{const e=this._intersector.updateFromGroundIntersection(a.target,c-d,a.target);null==a.targetFeatureId&&(a.targetSurfaceNormal=e)}}this._adjustStartEndPositions(e),e.notifyInputPointsChanged(),this.priority=z.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:I(e.target.position,this.view.spatialReference)}),({computation:e,targetPosition:t,targetElevationInfo:o,targetFeatureInfo:n,projectedTargetPosition:i})=>{null==i.pending?this._onTargetPositionChange(e,t,i.geometry,o,n):this._updatingHandles.addPromise(i.pending)},d)])}_connectComputationToObserver(e){return this._updatingHandles.add(()=>({computation:e,observer:this.analysisViewData.elevationAlignedObserver}),({computation:e})=>{this._externalObserverUpdate&&(e.inputPoints.isValid=!1,e.notifyInputPointsChanged())},d)}_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:n,observerFeatureId:i})=>{this._onObserverRenderSpacePositionChangeForComputation(e,t,o,n,i)},d)}_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.slice.plane,()=>{e.inputPoints.isValid=!1,e.notifyInputPointsChanged()})}_connectComputationToElevation(e){const t=(o,n)=>{const i=this.analysis.observer,r=e.target;let s=null,a=null,l=null,u=null,c=null,d=null;if(null!=i?.position){const e=I(i.position,this.view.spatialReference);if(null!=e.pending)return this._updatingHandles.addPromise(e.pending),void e.pending.finally(()=>t(o,n));s=e.geometry,a=i.elevationInfo,l=i.feature}if(null!=r.position){const e=I(r.position,this.view.spatialReference);if(null!=e.pending)return this._updatingHandles.addPromise(e.pending),void e.pending.finally(()=>t(o,n));u=e.geometry,c=r.elevationInfo,d=r.feature}null==s&&null==u||(S(o,n,J,this.view.spatialReference),null!=s&&j(J,s)&&this._onObserverPositionChange(null!=i?i.position:null,s,a,l,!1),null!=u&&j(J,u)&&this._onTargetPositionChange(e,r.position,u,c,d,!1),null!=s&&null!=u&&R(J,s,u)&&e.notifyInputPointsChanged())};return this.view.elevationProvider.on("elevation-change",({extent:e,spatialReference:o})=>t(e,o))}_connectComputationToTask(e){let t=null;const o={computation:e,interpolationInfo:{originalIntersection:T(),originalObserver:T(),originalTarget:T()}};return s([this._updatingHandles.add(()=>e.inputPoints,()=>{t=u(t),t=n(async e=>{await c(this._frameTask.schedule(()=>this._computeResult(o),e))})},{initial:!0,equals:()=>!1}),a(()=>t=u(t))])}_connectComputationToContent(e){return p(()=>this.view.pointsOfInterest?.contentGeometryUpdates.events,"request-update",t=>{const o=t?.renderBounds,{observerAdjusted:n,targetAdjusted:i}=e.inputPoints;(null==o||w(o,n,i))&&(e.inputPoints.isValid=!1,e.notifyInputPointsChanged())})}_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),this._connectComputationToContent(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){null!=t&&this._removeTarget(t),null!=e&&this._addTarget(e)}_addTarget(e){this._computations.some(t=>t.target===e)||this._computations.add(new F({target:e}))}_removeTarget(e){const t=this._computations.findIndex(t=>t.target===e);this._computations.removeAt(t)}_connectObserver(){return s([this._updatingHandles.add(()=>({observerPosition:null!=this.analysis.observer?this.analysis.observer.position:null,projectedObserverPosition:I(null!=this.analysis.observer?this.analysis.observer.position:null,this.view.spatialReference),observerElevationInfo:null!=this.analysis.observer?this.analysis.observer.elevationInfo:null,observerFeatureInfo:null!=this.analysis.observer?this.analysis.observer.feature:null}),({observerPosition:e,projectedObserverPosition:t,observerElevationInfo:o,observerFeatureInfo:n})=>{null==t.pending?this._onObserverPositionChange(e,t.geometry,o,n,!0):this._updatingHandles.addPromise(t.pending)},d)])}_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(null==e||null==o)return!1;const n=Z;o.toRenderCoords(e,n);const i=t.state.camera.computeScreenPixelSizeAt(n);return Math.abs((i-this._screenPixelSize)/this._screenPixelSize)>B}};function k(e,t){return e.hasZ?t??{mode:"absolute-height",offset:0}:{mode:"on-the-ground",offset:0}}function M({computation:e,interpolationInfo:t}){const{computationResult:o,inputPoints:n}=e,{start:i,end:r,intersection:s}=o,{originalIntersection:a,originalObserver:l,originalTarget:u}=t;if(m(s,a),n.isValid){const e=Z,t=y(l,a)/y(l,u);C(e,i,l),_(e,e,1-t),b(s,s,e),C(e,r,u),_(e,e,t),b(s,s,e),o.isValid=!0}else e.result=null,o.isValid=!1,o.isTargetVisible=!1}e([g({constructOnly:!0})],N.prototype,"analysis",void 0),e([g({constructOnly:!0})],N.prototype,"analysisViewData",void 0),e([g({constructOnly:!0})],N.prototype,"view",void 0),e([g()],N.prototype,"updating",null),e([g()],N.prototype,"priority",null),e([g()],N.prototype,"updateOnCameraChange",void 0),e([g()],N.prototype,"_computations",null),e([g()],N.prototype,"_elevationAlignedObserverPositionRenderSpace",null),e([g()],N.prototype,"_observerGroundOffsetRenderSpace",void 0),e([g()],N.prototype,"_effectiveObserverElevationMode",void 0),e([g()],N.prototype,"_observerFeatureId",void 0),e([g()],N.prototype,"_screenPixelSize",null),e([g({readOnly:!0})],N.prototype,"_updatingHandles",void 0),e([g()],N.prototype,"_frameTask",void 0),e([g()],N.prototype,"_isCameraDirty",null),N=e([h("esri.views.3d.analysis.LineOfSight.LineOfSightController")],N);const B=.1,Z=T(),q=E(),J=A();export{N as LineOfSightController};