UNPKG

@arcgis/core

Version:

ArcGIS Maps SDK for JavaScript: A complete 2D and 3D mapping and data visualization API

6 lines (5 loc) 8.5 kB
/* All material copyright ESRI, All Rights Reserved, unless otherwise specified. See https://js.arcgis.com/4.32/esri/copyright.txt for details. */ import e from"../../../../core/PooledArray.js";import{castRenderScreenPointArray3 as t,createRenderScreenPointArray3 as r}from"../../../../core/screenUtils.js";import{getMetersPerVerticalUnitForSR as i}from"../../../../core/unitUtils.js";import{g as n,n as s,f as o}from"../../../../chunks/vec32.js";import{create as l}from"../../../../core/libs/gl-matrix-2/factories/vec3f64.js";import{create as a,copy as c,negativeInfinity as u,width as h,height as d,expandPointInPlace as p}from"../../../../geometry/support/aaBoundingRect.js";import{create as m}from"../../../../geometry/support/ray.js";import{sv3d as g}from"../../../../geometry/support/vectorStacks.js";import{getElevationOffsetInMeters as y}from"../../../../support/elevationInfoUtils.js";import{ViewingMode as f}from"../../../ViewingMode.js";import{computeMapPointFromVec3d as R}from"../../support/hitTest.js";import{fromRenderAtEye as _,fromScreen as v}from"../../support/geometryUtils/ray.js";import{defaultTolerance as I,newIntersector as b}from"../../webgl-engine/lib/Intersector.js";import{StoreResults as w,IntersectorType as P}from"../../webgl-engine/lib/IntersectorInterfaces.js";import{isValidIntersectorResult as j,sliceFilterPredicate as M}from"../../webgl-engine/lib/intersectorUtils.js";import{HUDMaterial as U}from"../../webgl-engine/materials/HUDMaterial.js";class x{constructor(t,r,i){this.viewingMode=t,this._forEachLayer=r,this._view=i,this._externalIntersectionHandlers=new e,this._tolerance=I,this._tmpRay=m(),this._tmpRegion=a(),this._validateHUDIntersector=b(this.viewingMode),this._validateHUDIntersector.options.hud=!1}intersectScreen(e,t,r){return this.intersectRay(this._getPickRay(e,this._tmpRay),A(this.viewingMode),t,r)}intersectScreenFreePointFallback(e,t,r){return this.intersectRayFreePointFallback(this._getPickRay(e,this._tmpRay),t,r)}intersectRayFreePointFallback(e,t,r){return this.intersectRay(e,A(this.viewingMode),t,r)||this._intersectRayFreePointLocal(e,t)}intersectRay(e,t,r,i){return t.options.selectionMode=!1,t.options.store=w.MIN,this.computeIntersection(e,t,i),!!t.results.min&&t.results.min.getIntersectionPoint(r)}getCenterRayWithSubpixelOffset(e,t,r=.5,i=.5){return e.getRenderCenter(N,r,i),N[0]+=.0466,N[1]-=.0123,_(e,N,t)}intersectIntersectorScreen(e,t,r){this.computeIntersection(this._getPickRay(e,this._tmpRay),t,r)}intersectToolIntersectorScreen(e,t,r){const i=this._getPickRay(e,this._tmpRay);this.intersectToolIntersectorRay(i,t,r)}intersectToolIntersectorRay(e,t,r){t.options.selectionMode=!0,this.computeIntersection(e,t,r);const i=t.results.min;!!this._view.basemapTerrain&&this._view.basemapTerrain.opaque||j(i)&&i.intersector!==P.TERRAIN||(t.options.selectionMode=!1,this.computeIntersection(e,t,r))}setTolerance(e=I){this._tolerance=e}addIntersectionHandler(e){this._externalIntersectionHandlers.push(e),this._externalIntersectionHandlers.sort(((e,t)=>e.type===P.TERRAIN?1:t.type===P.TERRAIN?-1:0))}removeIntersectionHandler(e){null!=this._externalIntersectionHandlers.removeUnordered(e)&&this._externalIntersectionHandlers.sort(((e,t)=>e.type===P.TERRAIN?1:t.type===P.TERRAIN?-1:0))}_getPickRay(e,t){const r=this._view.state.camera;return v(r,e,t)}_intersectRayFreePointLocal(e,t){return this.viewingMode!==f.Local||null==e||n(t,e.origin,s(g.get(),e.direction)),!1}intersectElevationFromScreen(e,t,r=0,i=null){return this._intersectElevation(this._getPickRay(e,this._tmpRay),t,r,i)}_intersectElevation(e,r,l=0,a=null){if(null==e)return null;const c=this._view,{renderCoordsHelper:u}=c,h=i(c.spatialReference),d=null!=r?r.mode:"absolute-height",p=y(r)/h,m=("on-the-ground"!==d?p+l:0)*h/u.unitInMeters,{camera:f}=c.state;if("absolute-height"===d){const t=u?.getAltitude(f.eye),r=o(s(S,e.direction),u.worldUpAtPosition(f.eye,D));if(t<m&&r<0||t>=m&&r>0)return null;if(u.intersectInfiniteManifold(e,m,S)){const e=R(c,S);return e.z??=0,e.z-=p,e}return null}const _=t(g.get());f.projectToRenderScreen(e.origin,_);const v=new k(null,this._forEachLayer),{slicePlane:I}=c,j=null!=I?M(I):null,U=b(this.viewingMode);U.options.store=w.MIN,U.options.verticalOffset=m,U.options.normalRequired=!1;const x=e.origin,T=n(g.get(),x,e.direction);U.reset(x,T,f),U.point=_;const E=a?"type"in a&&"graphics"===a.type?e=>e.layerUid!==a.uid:e=>e.graphicUid!==a.uid:null;switch(d){case"relative-to-scene":{const e=e=>(!E||E(e))&&!!e.lastValidElevationBB;U.intersect(v.layers,_,this._tolerance,null,e),this._externalIntersectionHandlers.forAll((e=>{if(e.type===P.I3S||e.type===P.TERRAIN||e.type===P.TILES3D){const t=e.slicePlaneEnabled?j:null;e.intersect(U,t,U.rayBegin,U.rayEnd,_)}}));break}case"on-the-ground":case"relative-to-ground":this._externalIntersectionHandlers.forAll((e=>{if(e.isGround){const t=e.slicePlaneEnabled?j:null;e.intersect(U,t,U.rayBegin,U.rayEnd,_)}}))}if(U.results.min.getIntersectionPoint(S)){const e=R(c,S);return e.z=l,e}return null}computeIntersection(e,r,i,s){if(null==e)return;const o=this._view.state.camera,l=t(g.get());o.projectToRenderScreen(e.origin,l);const a=new k(i,this._forEachLayer);r.options.selectOpaqueTerrainOnly=!i||!("include"in i||"exclude"in i);const c=e.origin,u=n(g.get(),e.origin,e.direction);r.reset(c,u,o),r.intersect(a.layers,l,this._tolerance);const h=this._view.slicePlane,d=null!=h?M(h):null;r.intersect(a.sliceableLayers,l,this._tolerance,d);const p=i&&(i.requiresGroundFeedback||i.enableDraped);this._externalIntersectionHandlers.forAll((e=>{const t=e.layerUid,i=Array.isArray(t),n=i?t:[t];i&&(r.options.filteredLayerUids=[]);let o=!1;for(const s of n){!a.filterLayerUid(s)?i&&r.options.filteredLayerUids.push(s):o=!0}if(r.options.isFiltered=!o,e.isGround&&p||!r.options.isFiltered){const t=e.slicePlaneEnabled?d:null;e.intersect(r,t,c,u,l,s)}}));const m=g.get(),y=this._view.basemapTerrain;if(i&&i.enableDraped&&null!=y.spatialReference&&r.results.ground.getIntersectionPoint(m)){const e=y.overlayManager.renderer,t=this._view.renderCoordsHelper.spatialReference,i=g.get();this._view.renderCoordsHelper.fromRenderCoords(m,i,y.spatialReference),i[2]=this._view.elevationProvider?.getElevation(m[0],m[1],m[2],t,"ground")??0,e.intersect(r,i,r.results.ground,(e=>a.filterRenderGeometry(e)))}r.sortResults(),this._processHUDResults(r)}_processHUDResults(e){const t=e.results.hud;c(this._tmpRegion,u);const r=this._view.state.camera,i=[],n=this._tmpRegion,s=e=>{const t=new H(e),s=t.result.target.object.geometries.every((e=>e.material instanceof U&&e.material.parameters.occlusionTest));i.push({item:t,occlusionTest:s}),s&&(r.projectToRenderScreen(e.target.center,t.screenPoint),t.screenPoint[0]=Math.floor(t.screenPoint[0]),t.screenPoint[1]=Math.floor(t.screenPoint[1]),p(n,t.screenPoint))};e.sortResults(t.all),null!=t.min.dist&&s(t.min);for(const c of t.all)t.min.target.object!==c.target.object&&t.max.target.object!==c.target.object&&s(c);if(null!=t.max.dist&&t.max.target.object!==t.min.target.object&&s(t.max),!i.length)return;n[0]===n[2]&&(n[2]+=1),n[1]===n[3]&&(n[3]+=1);const o=r.fullWidth,l=r.fullHeight,a=Math.max(0,n[0]-T),m=Math.max(0,n[1]-T),g=Math.min(h(n)+2*T,o-a),y=Math.min(d(n)+2*T,l-m),f=g>0&&y>0?new Uint8Array(g*y*4):null;f&&this._view._stage.renderer.readHUDVisibility(a,m,g,y,f);let R=!0;const _=null==e.results.max.dist;let v=0;for(const{item:c,occlusionTest:u}of i){let t=!u;if(u&&f)for(const e of E){const r=4*(Math.min(c.screenPoint[0]+e[0],o)-n[0]+(Math.min(c.screenPoint[1]+e[1],l)-n[1])*g);if(r>=0&&r<f.length&&f[r]){t=!0;break}}t&&(R&&(e.results.min.copy(c.result),R=!1),_&&e.results.max.copy(c.result),e.options.store===w.ALL&&e.results.all.splice(v++,0,c.result))}}}const T=1,E=(()=>{const e=[],t=T;for(let r=-1;r<=t;r++)for(let i=-1;i<=t;i++)e.push([i+t,r+t]);return e})();class H{constructor(e){this.result=e,this.screenPoint=r()}}let L;function A(e){return L&&L.viewingMode===e||(L=b(e)),L}class k{constructor(e,t){this.layers=new Array,this.sliceableLayers=new Array,this.include=e?.include,this.exclude=e?.exclude,t((e=>{e.pickable&&this.filterLayerUid(e.apiLayerUid)&&(e.sliceable?this.sliceableLayers:this.layers).push(e)}))}filterLayerUid(e){const{include:t,exclude:r}=this;return null==e?null==t&&null==r:(null==t||t.has(e))&&(null==r||!r.has(e))}filterRenderGeometry(e){return this.filterLayerUid(e.layerUid)}}function F(e){return"object"==typeof e&&"intersect"in e}const S=l(),D=l(),N=r();export{x as SceneIntersectionHelper,F as isIntersectionHandler};