@arcgis/core
Version:
ArcGIS Maps SDK for JavaScript: A complete 2D and 3D mapping and data visualization API
6 lines (5 loc) • 8.98 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{_ as e}from"../../../chunks/tslib.es6.js";import t from"../../../core/Error.js";import{assertIsSome as i}from"../../../core/maybe.js";import{urlToObject as s}from"../../../core/urlUtils.js";import{property as r}from"../../../core/accessorSupport/decorators/property.js";import"../../../core/has.js";import"../../../core/Logger.js";import"../../../core/RandomLCG.js";import{subclass as a}from"../../../core/accessorSupport/decorators/subclass.js";import l from"../../../geometry/Extent.js";import n from"../../../geometry/Point.js";import o from"../../../geometry/SpatialReference.js";import c from"../RasterInfo.js";import m from"../RasterStorageInfo.js";import u from"../TileInfo.js";import{TilemapCache as h}from"../TilemapCache.js";import f from"./BaseRaster.js";import{setValidBoundary as p}from"../rasterFunctions/pixelUtils.js";import d from"../rasterTransforms/GCSShiftTransform.js";import{patchServiceInfo as y,fetchServiceRasterInfo as x}from"../../../rest/imageService/fetchRasterInfo.js";let g=class extends f{constructor(){super(...arguments),this._levelOffset=0,this._tilemapCache=null,this._slices=null,this.datasetFormat="RasterTileServer",this.tileType=null}async fetchRawTile(e,t,i,s={}){const{storageInfo:r,extent:a}=this.rasterInfo,{transposeInfo:l}=r,n=null!=l&&!!s.transposedVariableName;if(this._slices&&!n&&null==s.sliceId)return null;const o=n?0:r.maximumPyramidLevel-e+this._levelOffset,c=`${this.url}/tile/${o}/${t}/${i}`,m=this._slices?n?{variable:s.transposedVariableName}:{sliceId:s.sliceId||0}:null;let u,h;if(r.isBsqTile){const e=(s.bandIds?.length?s.bandIds:[0,1,2]).map((e=>this.request(c,{query:{...m,bandId:e},responseType:"array-buffer",signal:s.signal}))),t=await Promise.all(e),i=t.map((e=>e.data.byteLength)).reduce(((e,t)=>e+t)),r=new Uint8Array(i);h=[];let a=0;for(const{data:s}of t)h.push(a),r.set(new Uint8Array(s),a),a+=s.byteLength;u=r.buffer}else{u=(await this.request(c,{query:m,responseType:"array-buffer",signal:s.signal})).data}if(!u)return null;const f=n?l.tileSize:r.tileInfo.size,d=await this.decodePixelBlock(u,{width:f[0],height:f[1],planes:h?.length,offsets:h,pixelType:null,isPoint:"Elevation"===this.tileType,returnInterleaved:n,noDataValue:this.rasterInfo.noDataValue});if(null==d)return null;const y=r.blockBoundary[e];if("jpg"!==r.compression||i>y.minCol&&i<y.maxCol&&t>y.minRow&&t<y.maxRow)return d;const{origin:x,blockWidth:g,blockHeight:v}=r,{x:S,y:I}=this.getPyramidPixelSize(e),w=Math.round((a.xmin-x.x)/S)%g,b=Math.round((a.xmax-x.x)/S)%g||g,T=Math.round((x.y-a.ymax)/I)%v,j=Math.round((x.y-a.ymin)/I)%v||v,M=i===y.minCol?w:0,_=t===y.minRow?T:0,O=i===y.maxCol?b:g,R=t===y.maxRow?j:v;return p(d,{x:M,y:_},{width:O-M,height:R-_}),d}getSliceIndex(e){if(!this._slices||null==e||0===e.length)return null;const t=e;for(let i=0;i<this._slices.length;i++){const e=this._slices[i].multidimensionalDefinition;if(e.length===t.length&&!e.some((e=>{const i=t.find((t=>e.variableName===t.variableName&&t.dimensionName===e.dimensionName));if(!i)return!0;return(Array.isArray(e.values[0])?`${e.values[0][0]}-${e.values[0][1]}`:e.values[0])!==(Array.isArray(i.values[0])?`${i.values[0][0]}-${i.values[0][1]}`:i.values[0])})))return i}return null}async fetchVariableStatisticsHistograms(e,t){const i=this.request(this.url+"/statistics",{query:{variable:e,f:"json"},signal:t}).then((e=>e.data?.statistics)),s=this.request(this.url+"/histograms",{query:{variable:e,f:"json"},signal:t}).then((e=>e.data?.histograms)),r=await Promise.all([i,s]);return r[0]&&r[0].forEach((e=>{e.avg=e.mean,e.stddev=e.standardDeviation})),r[1]?.[0]?.counts?.length||(r[1]=null),{statistics:r[0]||null,histograms:r[1]||null}}async computeBestPyramidLevelForLocation(e,t={}){if(!this._tilemapCache)return 0;let i=this.identifyPixelLocation(e,0,t.datumTransformation);if(null===i)return null;let s=0;const{maximumPyramidLevel:r}=this.rasterInfo.storageInfo;let a=r-s+this._levelOffset;const l=i.srcLocation;for(;a>=0;){try{if("available"===await this._tilemapCache.fetchAvailability(a,i.row,i.col,t))break}catch{}if(a--,s++,i=this.identifyPixelLocation(l,s,t.datumTransformation),null===i)return null}return-1===a||null==i?null:s}async _open(e){const r=e?.signal,a=this.sourceJSON?{data:this.sourceJSON}:await this.request(this.url,{query:{f:"json"},signal:r});a.ssl&&(this.url=this.url.replace(/^http:/i,"https:"));const l=a.data;if(this.sourceJSON=l,!l)throw new t("imageserverraster:open","cannot initialize tiled image service, missing service info");if(!l.tileInfo)throw new t("imageserverraster:open","use ImageryLayer to open non-tiled image services");this._fixScaleInServiceInfo();const n=["jpg","jpeg","png","png8","png24","png32","mixed"];this.tileType=l.cacheType,null==this.tileType&&(n.includes(l.tileInfo.format.toLowerCase())?this.tileType="Map":"lerc"===l.tileInfo.format.toLowerCase()?this.tileType="Elevation":this.tileType="Raster"),this.datasetName=l.name?.slice(l.name.indexOf("/")+1)??"";const o=await this._fetchRasterInfo({signal:r});if(null==o)throw new t("image-server-raster:open","cannot initialize image service");y(o,l);const c="Map"===this.tileType?v(l.tileInfo,l):u.fromJSON(l.tileInfo);i(c);const[f,p]=this._computeMinMaxLOD(o,c),{extent:d,pixelSize:x}=o,g=.5/o.width*x.x,I=Math.max(x.x,x.y),{lods:w}=c;("Map"!==this.tileType&&0!==l.maxScale||Math.abs(x.x-x.y)>g||!w.some((e=>Math.abs(e.resolution-I)<g)))&&(x.x=x.y=f.resolution,o.width=Math.ceil((d.xmax-d.xmin)/x.x-.1),o.height=Math.ceil((d.ymax-d.ymin)/x.y-.1));const b=f.level-p.level,[T,j]=c.size,M=[],_=[];w.forEach(((e,t)=>{e.level>=p.level&&e.level<=f.level&&M.push({x:e.resolution,y:e.resolution}),t<w.length-1&&_.push(Math.round(10*e.resolution/w[t+1].resolution)/10)})),M.sort(((e,t)=>e.x-t.x));const O=this.computeBlockBoundary(d,T,j,c.origin,M,b),R=M.length>1?M.slice(1):null;let L;l.transposeInfo&&(L={tileSize:[l.transposeInfo.rows,l.transposeInfo.cols],packetSize:o.keyProperties?._yxs.PacketSize??0});const z=_.length<=1||_.length>=3&&_.slice(0,-1).every((e=>e===_[0]))?_[0]??2:Math.round(10/(p.resolution/f.resolution)**(-1/b))/10;if(o.storageInfo=new m({blockWidth:c.size[0],blockHeight:c.size[1],pyramidBlockWidth:c.size[0],pyramidBlockHeight:c.size[1],pyramidResolutions:R,pyramidScalingFactor:z,compression:c.format,origin:c.origin,firstPyramidLevel:1,maximumPyramidLevel:b,tileInfo:c,isBsqTile:!!l.bsq,transposeInfo:L,blockBoundary:O}),S(o),this._set("rasterInfo",o),l.capabilities.toLowerCase().includes("tilemap")){const e={tileInfo:o.storageInfo.tileInfo,parsedUrl:s(this.url),url:this.url,tileServers:[]};this._tilemapCache=new h({layer:e})}}async _fetchRasterInfo(e){const t=this.sourceJSON;if("Map"===this.tileType){const e=t.fullExtent||t.extent,i=Math.ceil((e.xmax-e.xmin)/t.pixelSizeX-.1),s=Math.ceil((e.ymax-e.ymin)/t.pixelSizeY-.1),r=o.fromJSON(t.spatialReference||e.spatialReference),a=new n({x:t.pixelSizeX,y:t.pixelSizeY,spatialReference:r});return new c({width:i,height:s,bandCount:3,extent:l.fromJSON(e),spatialReference:r,pixelSize:a,pixelType:"u8",statistics:null,keyProperties:{DataType:"processed"}})}const{signal:i}=e,s=x(this.url,this.sourceJSON,{signal:i,query:this.ioConfig.customFetchParameters}),r=t.hasMultidimensions?this.request(`${this.url}/slices`,{query:{f:"json"},signal:i}).then((e=>e.data?.slices)).catch((()=>null)):null,a=await Promise.all([s,r]);return this._slices=a[1],a[0]}_fixScaleInServiceInfo(){const{sourceJSON:e}=this;e.minScale&&e.minScale<0&&(e.minScale=0),e.maxScale&&e.maxScale<0&&(e.maxScale=0)}_computeMinMaxLOD(e,t){const{pixelSize:i}=e,s=.5/e.width*i.x,{lods:r}=t,a=t.lodAt(Math.max.apply(null,r.map((e=>e.level)))),l=t.lodAt(Math.min.apply(null,r.map((e=>e.level)))),{tileType:n}=this;if("Map"===n)return this._levelOffset=r[0].level,[a,l];if("Raster"===n){return[r.find((e=>e.resolution===i.x))??a,l]}const{minScale:o,maxScale:c}=this.sourceJSON;let m=a;c>0&&(m=r.find((e=>Math.abs(e.scale-c)<s)),m||(m=r.filter((e=>e.scale>c)).sort(((e,t)=>e.scale>t.scale?1:-1))[0]??a));let u=l;return o>0&&(u=r.find((e=>Math.abs(e.scale-o)<s))??l,this._levelOffset=u.level-l.level),[m,u]}};function v(e,t){if(!e)return null;const{minScale:i,maxScale:s,minLOD:r,maxLOD:a}=t;if(null!=r&&null!=a)return u.fromJSON({...e,lods:e.lods.filter((({level:e})=>null!=e&&e>=r&&e<=a))});if(0!==i&&0!==s){const t=e=>Math.round(1e4*e)/1e4,r=i?t(i):1/0,a=s?t(s):-1/0;return u.fromJSON({...e,lods:e.lods.filter((e=>{const i=t(e.scale);return i<=r&&i>=a}))})}return u.fromJSON(e)}function S(e){const{extent:t,spatialReference:i}=e;t.xmin>-1&&t.xmax>181&&i?.wkid&&i.isGeographic&&(e.nativeExtent=e.extent,e.transform=new d,e.extent=e.transform.forwardTransform(t))}e([r({type:String,json:{write:!0}})],g.prototype,"datasetFormat",void 0),e([r()],g.prototype,"tileType",void 0),g=e([a("esri.layers.support.rasterDatasets.ImageServerRaster")],g);const I=g;export{I as default};