@arcgis/core
Version:
ArcGIS Maps SDK for JavaScript: A complete 2D and 3D mapping and data visualization API
6 lines (5 loc) • 13.7 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 i from"../../../core/Logger.js";import{property as n}from"../../../core/accessorSupport/decorators/property.js";import"../../../core/has.js";import"../../../core/RandomLCG.js";import{subclass as s}from"../../../core/accessorSupport/decorators/subclass.js";import o from"../../../geometry/Extent.js";import{isAxesOrderReversedForWkid as r}from"../../ogc/crsUtils.js";import{getCapabilities as a,describeCoverage as l}from"../../ogc/wcsUtils.js";import c from"../DimensionalDefinition.js";import d from"./BaseRaster.js";import{convertOleDateTimeToEpoch as f}from"./multidimensionalUtils.js";import{parse as p}from"./multipartParser.js";import{standardizeInterpolations as u}from"./wcsCoverageParser.js";import{getFormat as h}from"../rasterFormats/RasterCodec.js";import{clip as m}from"../rasterFunctions/pixelUtils.js";const g=["nearest neighbor","bilinear","bicubic"],w=["nearest","linear","cubic"],v="response is not a supported multipart/related mediaType with inline tiff, switching to compatibility mode",y="response is not a supported multipart mediaType with inline tiff",x="response is base64 encoded which may impact layer display performance",I="server returns an exception",C=new Set(["1.0.0","1.1.0","1.1.1","1.1.2","2.0.1"]);let b=class extends d{constructor(){super(...arguments),this.datasetFormat="WCSServer",this.tileType="Raster"}get rasterId(){return`${this.url}-${this.coverageId}-${this.version}`}async fetchRawTile(e,i,n,s={}){if(this.isBlockOutside(e,i,n))return null;const{nativePixelSize:o,spatialReference:r}=this.rasterInfo,a=2**e,l=o.x*a,c=o.y*a,{blockWidth:d,blockHeight:f}=this.getBlockWidthHeight(e),{origin:p}=this.rasterInfo.storageInfo.tileInfo,u=this.getTileExtent({x:l,y:c},i,n,p,r,[d,f]),h=this.rasterInfo.extent,g=u.xmax>h.xmax,w=u.ymin<h.ymin,v=g||w;let y=u,x=d,I=f;if(v&&(y=u.clone().intersection(h),null!=y&&(g&&(x=Math.floor((y.xmax-y.xmin)/l),y.xmax=y.xmin+l*x),w&&(I=Math.floor((y.ymax-y.ymin)/c),y.ymin=y.ymax-c*I))),null==y||x<=1||I<=1)return null;const C=await this._getCoverage(y,x,I,a,s);if(!C)return null;const{coverageDescription:b}=this.coverageInfo,{noDataValue:$,multidimensionalInfo:S}=this.rasterInfo,{multidimensionalDefinition:j}=s;let T;if(null!=S&&null!=j&&j.length){const e=j[0].variableName;if("2.0"===b.version){const t=b.rangeType[0].find((t=>t.name===e));T=t?.nilValue}else if("1.1"===b.version){const t=b.range.find((t=>t.identifier===e));T=t?.nullValues}}const L=T??$,P=await this.decodePixelBlock(C,{width:x,height:I,planes:null,pixelType:null,tiffNoDataValue:Array.isArray(L)?L[0]:L,matchAllNoData:!0});if(null==P)return null;if(P&&(P.width!==x||P.height!==I))throw new t("wcsraster-fetch",`the response has unexpected dimension width: ${P.width}, height: {pixelBlock.height}`);return v?m(P,{x:0,y:0},{width:f,height:f}):P}async _open(e){const{customFetchParameters:i}=this.ioConfig,n=e?.signal,s=await a(this.url,{version:i?.version??this.version,customParameters:i,signal:n});if(this.capabilities=s,!this.version){let e=s.version.slice(0,3);"2.0"===e||"1.1"===e||"1.0"===e?this.version=s.version:(e=s.supportedVersions.find((e=>"2.0.1"===e))||s.supportedVersions.find((e=>"2.0"===e.slice(0,3)))||s.supportedVersions.find((e=>"1.1"===e.slice(0,3)))||s.supportedVersions.find((e=>"1.0"===e.slice(0,3)))||"1.0.0",this.version=e)}const{version:o}=this;if(!C.has(o))throw new t("wcsraster-open",`unsupported WCS version ${o}`);const{gridCoverages:r}=s;if(!r.length)throw new t("wcsraster-open","cannot find rectified grid coverages");this.coverageId??=r[0].id;const{coverageId:c}=this,d=r.find((e=>e.id===c));if(null==d)throw new t("wcsraster-open",`the coverageId ${c} does not exist in capabilities`);const f=await l(this.url,{coverageIds:[c],version:o,customParameters:i,signal:n});if(this.coverageInfo=f[0],"2.0"===o.slice(0,3)){const{coverageInfo:e}=this;e.lonLatEnvelope=d.lonLatEnvelope,e.supportedInterpolations=u(s.supportedInterpolations),this._patchDimensionValues201(c,n)}this.datasetName=this.coverageInfo.title;const{rasterInfo:p}=this.coverageInfo;if(this.createRemoteDatasetStorageInfo(p,512,512),this._set("rasterInfo",p),null==p.spatialReference)throw new t("wcsraster-open",`coverage without spatial reference is not supported: ${c}`);const{pixelType:h,bandCount:m}=await this._getPixelTypeAndBandCount(n);p.pixelType=h,1===p.bandCount&&m>1&&(p.bandCount=m),this.updateTileInfo()}async _patchDimensionValues201(e,t){const{coverageInfo:i}=this,n=i.rasterInfo.multidimensionalInfo?.variables,s=C.has("1.1.2")?"1.1.2":C.has("1.1.1")?"1.1.1":C.has("1.1.0")?"1.1.0":null,{customFetchParameters:o}=this.ioConfig;if(n&&s)try{const i=this.url.includes("/ImageServer/"),r=e.length>8&&e.startsWith("Coverage")&&i?e.slice(8):e,a=await l(this.url,{coverageIds:[r??e],version:s,customParameters:o,signal:t}).catch((()=>{if(r)return l(this.url,{coverageIds:[e],version:s,customParameters:o,signal:t})})),c=a?.[0].rasterInfo.multidimensionalInfo?.variables;if(c)for(const e of n){const t=c.find((({name:t})=>t===e.name));if(t?.dimensions?.length)for(let n=e.dimensions.length-1;n>=0;n--){const s=e.dimensions[n],o=t.dimensions.find((({name:e})=>e===s.name));o?o.values&&o.extent?.join(",")===s.extent?.join(",")&&(e.dimensions[n]={...s,values:o.values}):i&&e.dimensions.splice(n,1)}}}catch{}}async _getPixelTypeAndBandCount(e){const{pixelSize:n,extent:s,multidimensionalInfo:r}=this.rasterInfo,a=s.center,l=new o({xmin:a.x-n.x,xmax:a.x+n.x,ymin:a.y-n.y,ymax:a.y+n.y,spatialReference:s.spatialReference});let d=[];if(null!=r){const e=r.variables[0];d=[],e.dimensions.forEach((t=>{d.push(new c({variableName:e.name,dimensionName:t.name,values:t.hasRegularIntervals?t.extent?.[0]:t.values?.[0],isSlice:!0}))}))}const{coverageDescription:f}=this.coverageInfo,p={interpolation:"nearest",multidimensionalDefinition:d,signal:e},{version:u}=f,{ioConfig:h}=this,m="2.0"===u&&null==h.allowAnyMediaType||"1.1"===u&&null==h.use2GridOffsets;let g;try{g=await this._getCoverage(l,2,2,1,p,!0)}catch(y){if(!m)throw y;if("1.1"===u){if(!y.details?.isResolutionMismatch)throw y;h.use2GridOffsets=!0}}if(!g&&m&&("2.0"===u&&(h.allowAnyMediaType=!0),g=await this._getCoverage(l,2,2,1,p),g&&i.getLogger(this).warn("wcsraster:getcoverage",v)),!g)throw new t("wcsraster-open","unable to determine pixel type");const w=await this.decodePixelBlock(g,{width:2,height:2,planes:null,pixelType:null});if(null==w)throw new t("wcsraster-open","unable to determine pixel type");return{pixelType:w.pixelType,bandCount:w.getPlaneCount()??0}}async _getCoverage(e,n,s,o,r,a=!1){const{coverageDescription:l}=this.coverageInfo,{version:c}=l,d="2.0"===c?this._getCoverage201Parameters(e,n,s,o,r,l):"1.1"===c?this._getCoverage110Parameters(e,n,s,r,l):this._getCoverage100Parameters(e,n,s,r),f="2.0"===c?await this.request(this._constructWCS201Url(d),{signal:r.signal,responseType:"array-buffer"}):await this.request(this.url,{query:d,signal:r.signal,responseType:"array-buffer"});if("1.0"===c)return f.data;if("2.0"===c&&!1!==this.ioConfig.allowAnyMediaType){if("tiff"===h(f.data))return a&&(this.ioConfig.allowAnyMediaType=!0,i.getLogger(this).warn("wcsraster:getcoverage",v)),f.data}const u=p(f);if(u.isMultipart&&u.data){const e=u.data.find((e=>e.isValidImage));return a&&"base64"===e?.contentTransferEncoding&&i.getLogger(this).warn("wcsraster:getcoverage",x),e?.contentData}const m=new Uint8Array(f.data,0,Math.min(f.data.byteLength,2e3)),g=String.fromCharCode.apply(null,m).toLowerCase().includes("exception"),w=g&&String.fromCharCode.apply(null,m).includes("A non-zero RESX/RESY or WIDTH/HEIGHT is required but neither was provided");if(g)throw new t("wcsraster:getcoverage",I,{isResolutionMismatch:w});throw new t("wcsraster:getcoverage",y)}_getInterpolationIndex(e){return e&&this.coverageInfo.supportedInterpolations?.includes(e)?"nearest"===e?0:"bilinear"===e?1:"cubic"===e?2:0:0}_getCoverage100Parameters(e,t,i,n){const s=`${e.xmin},${e.ymin},${e.xmax},${e.ymax}`,o=e.spatialReference.wkid,r=(this.coverageInfo.supportedFormats||[]).find((e=>e.toLowerCase().includes("tiff")))||"GEOTIFF",{bandIds:a,interpolation:l}=n,c=this._getInterpolationIndex(l),d=a?a.map((e=>this.coverageInfo.bandNames[e])):null,f=g[c],{multidimensionalDefinition:p}=n;let u;if(null!=p&&null!=this.rasterInfo.multidimensionalInfo){const e=p.find((e=>"StdTime"===e.dimensionName));let t=e?.values;t&&t.length>0&&(Array.isArray(t[0])&&(t=t[0]),u=t.map((e=>$(e))).join(","))}return{service:"WCS",request:"GetCoverage",version:this.version,coverage:this.coverageId,format:r,crs:`EPSG:${o}`,bbox:s,width:t,height:i,time:u,interpolation:f,band:d?.join(",")}}_getCoverage110Parameters(e,t,i,n,s){const{multidimensionalDefinition:o,bandIds:a,interpolation:l}=n,c=e.spatialReference.wkid,d=`urn:ogc:def:crs:EPSG::${c}`,f=(this.coverageInfo.supportedFormats||[]).find((e=>e.toLowerCase().includes("tiff")))||"image/tiff",p=this._getInterpolationIndex(l),u=w[p],h=null==l||0===this.coverageInfo.supportedInterpolations?.indexOf(l),m=s.domain.spatialDomain,g=m.origin.x<=m.envelope.xmin&&m.origin.y<=m.envelope.ymin,v=e.width/t,y=e.height/i*(g?1:-1),x=g?[e.xmin,e.ymin]:[e.xmin,e.ymax],I=m.useEPSGAxis&&r(c),C=I?`${x[1]},${x[0]}`:`${x[0]},${x[1]}`,b=this.ioConfig.use2GridOffsets,S=I?b?`${y},${v}`:`${y},0,0,${v}`:b?`${v},${y}`:`${v},0,0,${y}`,j=v/2,T=e.xmin+j,L=e.xmax-j,P=Math.abs(y)/2,R=e.ymin+P,_=e.ymax-P,D=I?`${R},${T},${_},${L},${d}`:`${T},${R},${L},${_},${d}`,A=s.range.find((e=>e.axis.some((e=>e.identifier.toLowerCase().includes("band")))));let E,G=A&&u&&a?h?`${A.identifier}[${A.axis[0].identifier}[${a.join(",")}]]`:`${A.identifier}:${u}[${A.axis[0].identifier}[${a.join(",")}]]`:null;if(null!=o&&o.length)for(let r=0;r<o.length;r++){let e=o[r].values;const t=o[r].dimensionName?.toLowerCase(),i=o[r].variableName?.toLowerCase(),n=s.range.find((e=>e.identifier.toLowerCase()===i));if(e.length>0)if(Array.isArray(e[0])&&(e=e[0]),"stdtime"===t)E=e.map((e=>$(e))).join(",");else if(n){const i=n.axis.find((e=>e.identifier.toLowerCase()===t));i&&(G=h?n.identifier+"["+i.identifier+"["+e.join(",")+"]]":n.identifier+":"+u+"["+i.identifier+"["+e.join(",")+"]]")}r===o.length-1&&n&&!G&&(G=h?n.identifier:n.identifier+":"+u)}return{service:"WCS",request:"GetCoverage",version:this.version,identifier:this.coverageId,format:f,crs:`EPSG:${c}`,boundingbox:D,gridCS:"urn:ogc:def:cs:OGC:0.0:Grid2dSquareCS",gridType:"urn:ogc:def:method:WCS:1.1:2dGridIn2dCrs",gridOrigin:C,gridOffsets:S,gridBaseCRS:d,timeSequence:E,rangeSubset:G}}_getCoverage201Parameters(e,t,i,n,s,o){const{multidimensionalDefinition:r,interpolation:a}=s,l=this._getInterpolationIndex(a);let c=null;const{supportedInterpolations:d}=this.capabilities;if(d?.length)switch(l){case 0:c=d.find((e=>e.toLowerCase().includes("nearest")));break;case 1:c=d.find((e=>e.toLowerCase().includes("linear")));break;case 2:c=d.find((e=>e.toLowerCase().includes("cubic")||e.toLowerCase().includes("quadratic")))}const f=(this.coverageInfo.supportedFormats||[]).find((e=>e.toLowerCase().includes("tiff")))||"image/tiff",{bandNames:p}=this.coverageInfo,{boundedBy:u,domainSet:h,rangeType:m}=o,g=u.isEastFirst?0:1,w=1-g,{axisLabels:v}=u,y=v[g],x=v[w],I=`http://www.opengis.net/def/crs/EPSG/0/${e.spatialReference.wkid}`,C=I,b=[];b.push(`${y}(${e.xmin},${e.xmax})`),b.push(`${x}(${e.ymin},${e.ymax})`);const S=[];if(v.length>2)for(let _=2;_<v.length;_++){const e=h.origin[_];if(v[_].toLowerCase().includes("time")){let t=e.toString();u.uomLabels?.[_].toLowerCase().includes("ole")&&(S.push(v[_]),t=$(e,!0)),b.push(v[_]+",http://www.opengis.net("+t+")")}else b.push(v[_]+",http://www.opengis.net("+e+")")}let j=null;if(null!=r&&r.length){const e=[];m.forEach((t=>t.forEach((t=>e.push(t.name)))));const t=[];for(let i=0;i<r.length;i++){const n=v.find((e=>e===r[i].dimensionName)),s=e.find((e=>e===r[i].variableName));if(t.includes(s)||t.push(s),n){let e=r[i].values;if(e.length>0){Array.isArray(e[0])&&(e=e[0]);let t="";t=n.toLowerCase().includes("time")?e.map((e=>$(e))).join(","):e.join(",");const i=b.findIndex((e=>0===e.indexOf(n+",http://www.opengis.net")));-1===i&&b.push(n+",http://www.opengis.net("+t+")"),-1===i||b[i].includes("("+t+")")||b.splice(i,1,n+",http://www.opengis.net("+t+")")}}}t.length&&(j=t.join(","))}else if(p?.length>=2){j=(s.bandIds?s.bandIds.map((e=>p[e])):p).join(",")}const T=b.join("&subset="),L=!o.domainSet.hasSameAxisLabelsAsBoundedBy&&!1!==this.ioConfig.allowScaleFactor,P=L?null:`${y}(${t}),${x}(${i})`,R=L?1/n:null;return{service:"WCS",request:"GetCoverage",version:this.version,coverageId:this.coverageId,rangesubset:j,interpolation:c,scaleSize:P,scaleFactor:R,subset:T,format:f,mediaType:this.ioConfig.allowAnyMediaType?null:"multipart/related",outputcrs:I,subsettingcrs:C}}_constructWCS201Url(e){const t={...this.ioConfig.customFetchParameters,...e},i=[];Object.keys(t).forEach((e=>{const n=t[e];null!=n&&("subset"===e?"string"==typeof n&&n.split("&subset=").forEach((e=>{e&&i.push(`subset=${encodeURIComponent(e)}`)})):i.push(`${e}=${encodeURIComponent(n)}`))}));return`${encodeURI(this.url)}?${i.join("&")}`}};function $(e,t=!1){return(t?new Date(f(e)):new Date(e)).toISOString()}e([n({type:String,json:{write:!0}})],b.prototype,"datasetFormat",void 0),e([n({readOnly:!0})],b.prototype,"tileType",void 0),e([n({type:String,json:{write:!0}})],b.prototype,"version",void 0),e([n({type:String,json:{write:!0}})],b.prototype,"coverageId",void 0),e([n({readOnly:!0})],b.prototype,"rasterId",null),b=e([s("esri.layers.support.rasterDatasets.WCSRaster")],b);export{b as default};