@arcgis/core
Version:
ArcGIS Maps SDK for JavaScript: A complete 2D and 3D mapping and data visualization API
6 lines (5 loc) • 9 kB
JavaScript
/*
All material copyright ESRI, All Rights Reserved, unless otherwise specified.
See https://js.arcgis.com/4.33/esri/copyright.txt for details.
*/
import has from"../../../../core/has.js";import t from"../../../../core/Logger.js";import{deg2rad as e}from"../../../../core/mathUtils.js";import{throwIfAborted as n}from"../../../../core/promiseUtils.js";import r from"../../../../core/RandomLCG.js";import o from"../../../../geometry/Extent.js";import{getInfo as l}from"../../../../geometry/support/spatialReferenceUtils.js";const i=()=>t.getLogger("esri.views.2d.engine.flow.dataUtils"),a=10;async function s(t,e,r,o){const l=performance.now(),s=c(e,r),f=performance.now(),h=u(e,s,r.width,r.height),p=performance.now(),g=m(h,!0),y=performance.now(),x="Streamlines"===t?d(g,a):w(g),M=performance.now();return has("esri-2d-profiler")&&(i().info("I.1","_createFlowFieldFromData (ms)",Math.round(f-l)),i().info("I.2","_getStreamlines (ms)",Math.round(p-f)),i().info("I.3","createAnimatedLinesData (ms)",Math.round(y-p)),i().info("I.4","create{Streamlines|Particles}Mesh (ms)",Math.round(M-y)),i().info("I.5","createFlowMesh (ms)",Math.round(M-l)),i().info("I.6","Mesh size (bytes)",x.vertexData.buffer.byteLength+x.indexData.buffer.byteLength)),await Promise.resolve(),n(o),x}function c(t,e){const n=h(e.data,e.width,e.height,t.smoothing);if(t.interpolate){return(t,r)=>{const o=Math.floor(t),l=Math.floor(r);if(o<0||o>=e.width)return[0,0];if(l<0||l>=e.height)return[0,0];const i=t-o,a=r-l,s=o,c=l,f=o<e.width-1?o+1:o,u=l<e.height-1?l+1:l,h=n[2*(c*e.width+s)],m=n[2*(c*e.width+f)],d=n[2*(u*e.width+s)],w=n[2*(u*e.width+f)],p=n[2*(c*e.width+s)+1],g=n[2*(c*e.width+f)+1];return[(h*(1-a)+d*a)*(1-i)+(m*(1-a)+w*a)*i,(p*(1-a)+n[2*(u*e.width+s)+1]*a)*(1-i)+(g*(1-a)+n[2*(u*e.width+f)+1]*a)*i]}}return(t,r)=>{const o=Math.round(t),l=Math.round(r);return o<0||o>=e.width||l<0||l>=e.height?[0,0]:[n[2*(l*e.width+o)],n[2*(l*e.width+o)+1]]}}function f(t,e,n,r,o,l,i,a,s){const c=[];let f=n,u=r,h=0,[m,d]=e(f,u);m*=t.velocityScale,d*=t.velocityScale;const w=Math.sqrt(m*m+d*d);let p,g;c.push({x:f,y:u,t:h,speed:w});for(let y=0;y<t.verticesPerLine;y++){let[n,r]=e(f,u);n*=t.velocityScale,r*=t.velocityScale;const m=Math.sqrt(n*n+r*r);if(m<t.minSpeedThreshold)return c;const d=n/m,w=r/m;f+=d*t.segmentLength,u+=w*t.segmentLength;if(h+=t.segmentLength/m,Math.acos(d*p+w*g)>t.maxTurnAngle)return c;if(t.collisions){const t=Math.round(f*s),e=Math.round(u*s);if(t<0||t>i-1||e<0||e>a-1)return c;const n=l[e*i+t];if(-1!==n&&n!==o)return c;l[e*i+t]=o}c.push({x:f,y:u,t:h,speed:m}),p=d,g=w}return c}function u(t,e,n,o){const l=[],i=new r,a=1/Math.max(t.lineCollisionWidth,1),s=Math.round(n*a),c=Math.round(o*a),u=new Int32Array(s*c);for(let r=0;r<u.length;r++)u[r]=-1;const h=[];for(let r=0;r<o;r+=t.lineSpacing)for(let e=0;e<n;e+=t.lineSpacing)h.push({x:e,y:r,sort:i.getFloat()});h.sort(((t,e)=>t.sort-e.sort));for(const{x:r,y:m}of h)if(i.getFloat()<t.density){const n=f(t,e,r,m,l.length,u,s,c,a);if(n.length<2)continue;l.push(n)}return l}function h(t,e,n,r){if(0===r)return t;const o=Math.round(3*r),l=new Array(2*o+1);let i=0;for(let c=-o;c<=o;c++){const t=Math.exp(-c*c/(r*r));l[c+o]=t,i+=t}for(let c=-o;c<=o;c++)l[c+o]/=i;const a=new Float32Array(t.length);for(let c=0;c<n;c++)for(let n=0;n<e;n++){let r=0,i=0;for(let a=-o;a<=o;a++){if(n+a<0||n+a>=e)continue;const s=l[a+o];r+=s*t[2*(c*e+(n+a))],i+=s*t[2*(c*e+(n+a))+1]}a[2*(c*e+n)]=r,a[2*(c*e+n)+1]=i}const s=new Float32Array(t.length);for(let c=0;c<e;c++)for(let t=0;t<n;t++){let r=0,i=0;for(let s=-o;s<=o;s++){if(t+s<0||t+s>=n)continue;const f=l[s+o];r+=f*a[2*((t+s)*e+c)],i+=f*a[2*((t+s)*e+c)+1]}s[2*(t*e+c)]=r,s[2*(t*e+c)+1]=i}return s}function m(t,e){const n=new r,o=t.reduce(((t,e)=>t+e.length),0),l=new Float32Array(4*o),i=new Array(t.length);let a=0,s=0;for(const r of t){const t=a;for(const e of r)l[4*a]=e.x,l[4*a+1]=e.y,l[4*a+2]=e.t,l[4*a+3]=e.speed,a++;i[s++]={startVertex:t,numberOfVertices:r.length,totalTime:r[r.length-1].t,timeSeed:e?n.getFloat():0}}return{lineVertices:l,lineDescriptors:i}}function d(t,e){const n=9,{lineVertices:r,lineDescriptors:o}=t;let l=0,i=0;for(const m of o){l+=2*m.numberOfVertices;i+=6*(m.numberOfVertices-1)}const a=new Float32Array(l*n),s=new Uint32Array(i);let c=0,f=0;function u(){s[f++]=c-2,s[f++]=c,s[f++]=c-1,s[f++]=c,s[f++]=c+1,s[f++]=c-1}function h(t,e,r,o,l,i,s,f){const u=c*n;let h=0;a[u+h++]=t,a[u+h++]=e,a[u+h++]=1,a[u+h++]=r,a[u+h++]=i,a[u+h++]=s,a[u+h++]=o/2,a[u+h++]=l/2,a[u+h++]=f,c++,a[u+h++]=t,a[u+h++]=e,a[u+h++]=-1,a[u+h++]=r,a[u+h++]=i,a[u+h++]=s,a[u+h++]=-o/2,a[u+h++]=-l/2,a[u+h++]=f,c++}for(const m of o){const{totalTime:t,timeSeed:n}=m;let o=null,l=null,i=null,a=null,s=null,c=null;for(let f=0;f<m.numberOfVertices;f++){const d=r[4*(m.startVertex+f)],w=r[4*(m.startVertex+f)+1],p=r[4*(m.startVertex+f)+2],g=r[4*(m.startVertex+f)+3];let y=null,x=null,M=null,A=null;if(f>0){y=d-o,x=w-l;const r=Math.sqrt(y*y+x*x);if(y/=r,x/=r,f>1){let t=y+s,n=x+c;const r=Math.sqrt(t*t+n*n);t/=r,n/=r;const o=Math.min(1/(t*y+n*x),e);t*=o,n*=o,M=-n,A=t}else M=-x,A=y;null!==M&&null!==A&&(h(o,l,i,M,A,t,n,g),u())}o=d,l=w,i=p,s=y,c=x,a=g}h(o,l,i,-c,s,t,n,a)}return{vertexData:a,indexData:s}}function w(t){const e=16,n=1,r=2,{lineVertices:o,lineDescriptors:l}=t;let i=0,a=0;for(const U of l){const t=U.numberOfVertices-1;i+=4*t*2,a+=6*t*2}const s=new Float32Array(i*e),c=new Uint32Array(a);let f,u,h,m,d,w,p,g,y,x,M,A,I,V,F=0,v=0;function D(){c[v++]=F-8,c[v++]=F-7,c[v++]=F-6,c[v++]=F-7,c[v++]=F-5,c[v++]=F-6,c[v++]=F-4,c[v++]=F-3,c[v++]=F-2,c[v++]=F-3,c[v++]=F-1,c[v++]=F-2}function b(t,o,l,i,a,c,f,u,h,m,d,w,p,g){const y=F*e;let x=0;for(const e of[n,r])for(const n of[1,2,3,4])s[y+x++]=t,s[y+x++]=o,s[y+x++]=l,s[y+x++]=i,s[y+x++]=f,s[y+x++]=u,s[y+x++]=h,s[y+x++]=m,s[y+x++]=e,s[y+x++]=n,s[y+x++]=p,s[y+x++]=g,s[y+x++]=a/2,s[y+x++]=c/2,s[y+x++]=d/2,s[y+x++]=w/2,F++}function S(t,e){let n=y+M,r=x+A;const o=Math.sqrt(n*n+r*r);n/=o,r/=o;const l=y*n+x*r;n/=l,r/=l;let i=M+I,a=A+V;const s=Math.sqrt(i*i+a*a);i/=s,a/=s;const c=M*i+A*a;i/=c,a/=c,b(f,u,h,m,-r,n,d,w,p,g,-a,i,t,e),D()}function k(t,e,n,r,o,l){if(y=M,x=A,M=I,A=V,null==y&&null==x&&(y=M,x=A),null!=d&&null!=w){I=t-d,V=e-w;const n=Math.sqrt(I*I+V*V);I/=n,V/=n}null!=y&&null!=x&&S(o,l),f=d,u=w,h=p,m=g,d=t,w=e,p=n,g=r}function L(t,e){y=M,x=A,M=I,A=V,null==y&&null==x&&(y=M,x=A),null!=y&&null!=x&&S(t,e)}for(const U of l){f=null,u=null,h=null,m=null,d=null,w=null,p=null,g=null,y=null,x=null,M=null,A=null,I=null,V=null;const{totalTime:t,timeSeed:e}=U;for(let n=0;n<U.numberOfVertices;n++){k(o[4*(U.startVertex+n)],o[4*(U.startVertex+n)+1],o[4*(U.startVertex+n)+2],o[4*(U.startVertex+n)+3],t,e)}L(t,e)}return{vertexData:s,indexData:c}}function p(t,n){const r=n.pixels,{width:o,height:l}=n,i=new Float32Array(o*l*2),a=n.mask||new Uint8Array(o*l*2);if(n.mask||a.fill(255),"vector-uv"===t)for(let e=0;e<o*l;e++)i[2*e]=r[0][e],i[2*e+1]=-r[1][e];else if("vector-magdir"===t)for(let s=0;s<o*l;s++){const t=r[0][s],n=e(r[1][s]),o=Math.cos(n-Math.PI/2),l=Math.sin(n-Math.PI/2);i[2*s]=o*t,i[2*s+1]=l*t}return{data:i,mask:a,width:o,height:l}}async function g(t,e,n,r,a,s){const c=performance.now(),f=l(e.spatialReference);if(!f){const o=await y(t,e,n,r,a,s);return has("esri-2d-profiler")&&i().info("I.7","loadImagery, early exit (ms)",Math.round(performance.now()-c)),has("esri-2d-profiler")&&i().info("I.9","Number of parts",1),o}const[u,h]=f.valid,m=h-u,d=Math.ceil(e.width/m),w=e.width/d,p=Math.round(n/d);let g=e.xmin;const x=[],M=performance.now();for(let l=0;l<d;l++){const n=new o({xmin:g,xmax:g+w,ymin:e.ymin,ymax:e.ymax,spatialReference:e.spatialReference});x.push(y(t,n,p,r,a,s)),g+=w}const A=await Promise.all(x);has("esri-2d-profiler")&&i().info("I.8","All calls to _fetchPart (ms)",Math.round(performance.now()-M)),has("esri-2d-profiler")&&i().info("I.9","Number of parts",A.length);const I={data:new Float32Array(n*r*2),mask:new Uint8Array(n*r),width:n,height:r};let V=0;for(const o of A){for(let t=0;t<o.height;t++)for(let e=0;e<o.width;e++)V+e>=n||(I.data[2*(t*n+V+e)]=o.data[2*(t*o.width+e)],I.data[2*(t*n+V+e)+1]=o.data[2*(t*o.width+e)+1],I.mask[t*n+V+e]=o.mask[t*o.width+e]);V+=o.width}return has("esri-2d-profiler")&&i().info("I.10","loadImagery, general exit (ms)",Math.round(performance.now()-c)),I}async function y(t,e,n,r,o,l){const i={requestProjectedLocalDirections:!0,signal:l};if(null!=o&&(i.timeExtent=o),"imagery"===t.type){await t.load({signal:l});const o=await t.internalFetchImage(e,n,r,i);if(null==o?.pixelData?.pixelBlock)return{data:new Float32Array(n*r*2),mask:new Uint8Array(n*r),width:n,height:r};return p(t.rasterInfo.dataType,o.pixelData.pixelBlock)}await t.load({signal:l});const a=await t.fetchPixels(e,n,r,i);if(null==a?.pixelBlock)return{data:new Float32Array(n*r*2),mask:new Uint8Array(n*r),width:n,height:r};return p(t.serviceRasterInfo.dataType,a.pixelBlock)}export{m as createAnimatedLinesData,c as createFlowFieldFromData,s as createFlowMesh,w as createParticlesMesh,d as createStreamlinesMesh,u as getStreamlines,g as loadImagery};