@arcgis/core
Version:
ArcGIS Maps SDK for JavaScript: A complete 2D and 3D mapping and data visualization API
3 lines (2 loc) • 6.71 kB
JavaScript
/* COPYRIGHT Esri - https://js.arcgis.com/5.0.8/LICENSE.txt */
import has from"../../../core/has.js";import t from"../../../core/Logger.js";import{moduloPositive as e,deg2rad as r}from"../../../core/mathUtils.js";import o from"../../../core/RandomLCG.js";import{Seconds as n}from"../../../core/time.js";import i from"../../../geometry/Extent.js";import{getInfo as a}from"../../../geometry/support/spatialReferenceUtils.js";const s=()=>t.getLogger("esri.views.support.flow.dataUtils");function l(t,e,r,n,i){if(t.density<=0)return[];const{positions:a}=i,s=[],l=new o,c=1/Math.max(t.lineCollisionWidth,1),d=Math.round(r*c),u=Math.round(n*c),m=new Int32Array(d*u);for(let o=0;o<m.length;o++)m[o]=-1;const p={raster:m,width:d,height:u,resolutionFactor:c},w={},g=t.lineSpacing/Math.sqrt(t.density),y=Math.floor(n/g),x=Math.floor(r/g);for(let o=0;o<y;o++){const t=o*g;for(let e=0;e<x;e++){const r=e*g;w[`${e}-${o}`]={x:r,y:t,positions:[]}}}for(const{x:o,y:h}of a){const t=w[`${Math.floor(o/g)}-${Math.floor(h/g)}`];t&&t.positions.push([o,h])}const M=[];for(const o in w){const t=w[o];if(0===t.positions.length)M.push({x:t.x+g/2,y:t.y+g/2,sort:.66+.33*l.getFloat(),stage:0});else{const[e]=t.positions.splice(0,1);M.push({x:e[0],y:e[1],sort:.33*l.getFloat(),stage:1});for(const[r,o]of t.positions)M.push({x:r,y:o,sort:.33+.33*l.getFloat(),stage:2})}}M.sort((t,e)=>t.sort-e.sort);for(const{x:o,y:v,stage:A}of M){if(s.length>=t.maxNumberOfStreamlines)break;const i=t.onlyForwardTracing?h(1,t,e,o,v,[r,n],s.length,p):f(t,e,o,v,[r,n],s.length,l,p);i.length<2||s.push({stage:A,vertices:i})}return s}function c(t,e){const r=d(e.data,e.width,e.height,t.smoothing);if(t.interpolate){return(t,o)=>{const n=Math.floor(t),i=Math.floor(o);if(n<0||n>=e.width)return[0,0];if(i<0||i>=e.height)return[0,0];const a=t-n,s=o-i,l=n,c=i,h=n<e.width-1?n+1:n,f=i<e.height-1?i+1:i,d=r[2*(c*e.width+l)],u=r[2*(c*e.width+h)],m=r[2*(f*e.width+l)],p=r[2*(f*e.width+h)],w=r[2*(c*e.width+l)+1],g=r[2*(c*e.width+h)+1];return[(d*(1-s)+m*s)*(1-a)+(u*(1-s)+p*s)*a,(w*(1-s)+r[2*(f*e.width+l)+1]*s)*(1-a)+(g*(1-s)+r[2*(f*e.width+h)+1]*s)*a]}}return(t,o)=>{const n=Math.round(t),i=Math.round(o);return n<0||n>=e.width||i<0||i>=e.height?[0,0]:[r[2*(i*e.width+n)],r[2*(i*e.width+n)+1]]}}function h(t,r,o,i,a,s,l,c){const h=[],{raster:f,width:d,height:u,resolutionFactor:m}=c;let p=i,w=a,g=n(0),[y,x]=o(p,w);y*=r.velocityScale,x*=r.velocityScale;const M=Math.sqrt(y*y+x*x);let v,A;h.push({x:p,y:w,time:g,speed:M});for(let k=0;k<r.verticesPerLine;k++){let[i,a]=o(p,w);i*=r.velocityScale,a*=r.velocityScale;const c=Math.sqrt(i*i+a*a);if(c<r.minSpeedThreshold)return h;const y=t*i/c,x=t*a/c;p+=y*r.segmentLength,w+=x*r.segmentLength,r.wrapAround&&(p=e(p,s[0]));const M=t*r.segmentLength/c;if(g=n(g+M),Math.acos(y*v+x*A)>r.maxTurnAngle)return h;if(r.collisions){let t=Math.round(p*m);const o=Math.round(w*m);if(r.wrapAround&&(t=e(t,d)),t<0||t>d-1||o<0||o>u-1)return h;const n=f[o*d+t];if(-1!==n&&n!==l)return h;f[o*d+t]=l}h.push({x:p,y:w,time:g,speed:c}),v=y,A=x}return h}function f(t,e,r,o,n,i,a,s){const l=Math.round((.2+.6*a.getFloat())*t.verticesPerLine),c=t.verticesPerLine-l,f=h(-1,{...t,verticesPerLine:c},e,r,o,n,i,s),d=h(1,{...t,verticesPerLine:l},e,r,o,n,i,s),u=f.reverse();u.splice(-1,1);return u.concat(d)}function d(t,e,r,o){if(0===o)return t;const n=Math.round(3*o),i=new Array(2*n+1);let a=0;for(let c=-n;c<=n;c++){const t=Math.exp(-c*c/(o*o));i[c+n]=t,a+=t}for(let c=-n;c<=n;c++)i[c+n]/=a;const s=new Float32Array(t.length);for(let c=0;c<r;c++)for(let r=0;r<e;r++){let o=0,a=0;for(let s=-n;s<=n;s++){if(r+s<0||r+s>=e)continue;const l=i[s+n];o+=l*t[2*(c*e+(r+s))],a+=l*t[2*(c*e+(r+s))+1]}s[2*(c*e+r)]=o,s[2*(c*e+r)+1]=a}const l=new Float32Array(t.length);for(let c=0;c<e;c++)for(let t=0;t<r;t++){let o=0,a=0;for(let l=-n;l<=n;l++){if(t+l<0||t+l>=r)continue;const h=i[l+n];o+=h*s[2*((t+l)*e+c)],a+=h*s[2*((t+l)*e+c)+1]}l[2*(t*e+c)]=o,l[2*(t*e+c)+1]=a}return l}async function u(t,e,r,o,n,l){const c=performance.now(),h=a(e.spatialReference);if(!h){const i=await m(t,e,r,o,n,l);return has("esri-2d-profiler")&&s().info("I.7","loadImagery, early exit (ms)",Math.round(performance.now()-c)),has("esri-2d-profiler")&&s().info("I.9","Number of parts",1),i}const[f,d]=h.valid,u=d-f,p=Math.ceil(e.width/u),w=e.width/p,g=Math.round(r/p);let y=e.xmin;const x=[],M=performance.now();for(let a=0;a<p;a++){const r=new i({xmin:y,xmax:y+w,ymin:e.ymin,ymax:e.ymax,spatialReference:e.spatialReference});x.push(m(t,r,g,o,n,l)),y+=w}const v=await Promise.all(x);if(has("esri-2d-profiler")&&s().info("I.8","All calls to _fetchPart (ms)",Math.round(performance.now()-M)),has("esri-2d-profiler")&&s().info("I.9","Number of parts",v.length),1===v.length)return has("esri-2d-profiler")&&s().info("I.10","loadImagery, general exit without stitching back (ms)",Math.round(performance.now()-c)),v[0];const A={data:new Float32Array(r*o*2),mask:new Uint8Array(r*o),width:r,height:o};let k=0;for(const i of v){for(let t=0;t<i.height;t++)for(let e=0;e<i.width;e++)k+e>=r||(A.data[2*(t*r+k+e)]=i.data[2*(t*i.width+e)],A.data[2*(t*r+k+e)+1]=i.data[2*(t*i.width+e)+1],A.mask[t*r+k+e]=i.mask[t*i.width+e]);k+=i.width}return has("esri-2d-profiler")&&s().info("I.10","loadImagery, general exit (ms)",Math.round(performance.now()-c)),A}async function m(t,e,r,o,n,i){const a={requestProjectedLocalDirections:!0,signal:i,interpolation:"bilinear"};if(null!=n&&(a.timeExtent=n),"imagery"===t.type){await t.load({signal:i});const n=await t.internalFetchImage(e,r,o,a);if(null==n?.pixelData?.pixelBlock)return{data:new Float32Array(r*o*2),mask:new Uint8Array(r*o),width:r,height:o};return p(t.rasterInfo.dataType,n.pixelData.pixelBlock)}await t.load({signal:i});const s=await t.fetchPixels(e,r,o,a);if(null==s?.pixelBlock)return{data:new Float32Array(r*o*2),mask:new Uint8Array(r*o),width:r,height:o};return p(t.serviceRasterInfo.dataType,s.pixelBlock)}function p(t,e,o=e.width,n=e.height,i=0,a=0){const s=e.pixels,l=o*n,c=2,h=new Float32Array(l*c),f=e.width,d=(t,e)=>t+i+(e+a)*f,u=(t,e)=>t+e*o;let m;if(null!=e.mask)if(o!==e.width||n!==e.height||0!==i||0!==a){m=new Uint8Array(l*c);const t=e.mask;for(let e=0;e<n;++e)for(let r=0;r<o;++r){const o=d(r,e),n=u(r,e);m[c*n]=t[c*o],m[c*n+1]=t[c*o+1]}}else m=e.mask;else m=new Uint8Array(l*c),m.fill(255);if("vector-uv"===t)for(let r=0;r<n;++r)for(let t=0;t<o;++t){const e=d(t,r),o=u(t,r);h[c*o]=s[0][e],h[c*o+1]=-s[1][e]}else if("vector-magdir"===t){const{cos:t,sin:e}=Math;for(let i=0;i<n;++i)for(let n=0;n<o;++n){const o=d(n,i),a=u(n,i),l=s[0][o],f=r(s[1][o]),m=t(f-Math.PI/2),p=e(f-Math.PI/2);h[c*a]=m*l,h[c*a+1]=p*l}}return{data:h,mask:m,width:o,height:n}}export{c as createFlowFieldFromData,u as loadImagery,p as toFlowData,l as traceFlowPaths};