@arcgis/core
Version:
ArcGIS Maps SDK for JavaScript: A complete 2D and 3D mapping and data visualization API
3 lines (2 loc) • 15.3 kB
JavaScript
/* COPYRIGHT Esri - https://js.arcgis.com/5.0.8/LICENSE.txt */
import e from"../../../geometry/Extent.js";import t from"../../../geometry/Polygon.js";import{isAxesOrderReversedForWkid as n}from"../../ogc/crsUtils.js";import{convertOleDateTimeToEpoch as i,getDimensionValues as s}from"./multidimensionalUtils.js";import{getElements as a,isSameTagIgnoreNS as o,getElementValue as l,getElementValues as r,getNodeNameIgnoreNS as u,getElement as m,getSpaceDelimitedNumericValues as p}from"./xmlUtilities.js";import c from"../../support/RasterInfo.js";function d(e){e.variables.forEach(e=>e.dimensions.forEach(e=>e.values??=s(e)))}function f(e){return{requestResponseCRSs:r(e,"requestResponseCRSs").map(e=>e.split(":")[1]),nativeCRSs:r(e,"nativeCRSs").map(e=>e.split(":")[1])}}function g(e,t){const n=r(e,"1.0.0"===t?"interpolationMethod":"InterpolationMethod"),i="1.0.0"===t?e.getAttribute("default"):l(e,"InterpolationMethods/Default");return null!=i?[i].concat(n.filter(e=>e.toLowerCase()!==i.toLowerCase())):n}function h(e){return null==e?["nearest"]:e.map(e=>{const t=e.toLowerCase();return t.includes("nearest")?"nearest":t.includes("linear")?"bilinear":t.includes("cubic")?"cubic":null}).filter(e=>!!e)}function b(t){const n=a(t,"pos"),i=p(n[0]),s=p(n[1]);return new e({xmin:i[0],ymin:i[1],xmax:s[0],ymax:s[1],spatialReference:{wkid:4326}})}function x(e,t){const n=r(e,t);return n?.length&&""!==n[0]&&!isNaN(Number(n[0]))?n.map(e=>Number(e)):null}function v(e){const t=p(e,"MinimumValue"),n=p(e,"MaximumValue");return t.length&&n.length?t.map((e,t)=>({min:e,max:n[t],avg:-1,stddev:-1})):null}function D(e){return null==e?null:e.every(t=>t===e[0])?e[0]:e}function y(e){const t=[],n=a(e,"RangeSet");let i=[];for(let s=0;s<n.length;s++){const e=l(n[s],"name"),o=l(n[s],"label"),u=[],m=x(n[s],"nullValues/singleValue"),p=a(n[s],"AxisDescription");for(let t=0;t<p.length;t++){const e=l(p[t],"name"),n=l(p[t],"label"),s=r(p[t],"singleValue");if(0===s.length){const e=l(p[t],"min"),n=l(p[t],"max"),i=Number(l(p[t],"res"))||1;if(null!==e&&null!==n)for(let t=parseInt(e,10);t<=parseInt(n,10);t+=i)s.push(t.toString())}"band"===e.toLowerCase()&&(i=s),u.push({name:e,label:n,values:s})}t.push({name:e,label:o,nullValues:m,axis:u})}return{rangeSet:t,bandNames:i}}function w(e=null){if(!e)return{resolution:null,units:null};let t=e.toUpperCase();const n=["Y","M","D"],i=["H","M","S"],s=["Years","Months","Days","Hours","Minutes","Seconds"];let a,o,l;return t.includes("PT")?(t=t.slice(2),l=i.findIndex(e=>t.includes(e)),a=s[3+l],o=parseFloat(t.slice(0,-1))):(t=t.slice(1),l=n.findIndex(e=>t.includes(e)),l>-1&&(a=s[l]),o=parseFloat(t.slice(0,-1))),{resolution:o,units:a}}function S(e){const t=a(e,"timeposition");if(t.length>0){const e=[];for(let n=0;n<t.length;n++)e.push(new Date(l(t[n])));return{begin:e[0],end:e[e.length-1],values:e}}const n=m(e,"timePeriod")||m(e,"TimePeriod");if(n){return{begin:new Date(l(n,"beginPosition")||l(n,"BeginPosition")),end:new Date(l(n,"endPosition")||l(n,"EndPosition")),...w(l(n,"timeResolution")||l(n,"TimeResolution"))}}return null}function I(t){const n=m(t,"spatialDomain"),i=m(n,"Envelope")||m(n,"EnvelopeWithTimePeriod"),s=i.getAttribute("srsName").split(":"),o=s[s.length-1],r=a(i,"pos"),u=p(r[0]),c=p(r[1]),d=parseInt(o,10),f=isNaN(d)?null:{wkid:d},g=new e({xmin:u[0],ymin:u[1],xmax:c[0],ymax:c[1],spatialReference:f}),h=m(n,"RectifiedGrid"),b=l(h,"low").split(" "),x=l(h,"high").split(" "),v=parseInt(x[0],10)-parseInt(b[0],10)+1,D=parseInt(x[1],10)-parseInt(b[1],10)+1,y=p(n,"origin/pos"),w=a(n,"offsetVector"),I={envelope:g,columns:v,rows:D,offset:{x:parseFloat(l(w[0]).split(" ")[0]),y:parseFloat(l(w[1]).split(" ")[1])},origin:{x:y[0],y:y[1]}},L=m(t,"temporalDomain")||m(t,"TemporalDomain");return{spatialDomain:I,temporalDomain:L?S(L):null}}function L(e){const t={version:"1.0"};let n,i=[];for(let c=0;c<e.childNodes.length;c++){const s=e.childNodes[c];if(1===s.nodeType)if(o(s,"description"))t.description=l(s);else if(o(s,"name"))t.name=l(s);else if(o(s,"label"))t.label=l(s);else if(o(s,"supportedFormats"))t.supportedFormats=r(s,"formats");else if(o(s,"supportedCRSs"))t.supportedCRSs=f(s);else if(o(s,"supportedInterpolations"))t.supportedInterpolations=g(s,"1.0.0");else if(o(s,"lonLatEnvelope"))t.lonLatEnvelope=b(s);else if(o(s,"rangeSet")){const e=y(s);t.rangeSet=e.rangeSet,i=e.bandNames;const a=e.rangeSet[0].nullValues;a?.length&&(n=D(a))}else o(s,"domainSet")&&(t.domainSet=I(s))}const s=h(t.supportedInterpolations),{name:a,description:u,label:m,lonLatEnvelope:p,supportedFormats:d}=t,{spatialDomain:x}=t.domainSet,v={x:Math.abs(x.offset.x),y:Math.abs(x.offset.y)},w=C(t.domainSet),S=new c({width:x.columns,height:x.rows,pixelSize:v,pixelType:"unknown",extent:x.envelope,spatialReference:x.envelope.spatialReference,bandCount:i.length||1,noDataValue:n,multidimensionalInfo:w});return{id:a,title:t.name,description:u||m,lonLatEnvelope:p,rasterInfo:S,bandNames:i,supportedFormats:d,supportedInterpolations:s,coverageDescription:t,version:"1.0.0",useEPSGAxis:!1}}function C(e){if(!e.temporalDomain)return null;const{begin:t,end:n,values:i,units:s,resolution:a}=e.temporalDomain,o={variables:[{name:"default",description:"",dimensions:[{name:"StdTime",description:"",unit:"ISO8601",values:i?.map(e=>e.getTime()),hasRegularIntervals:!i,interval:a,intervalUnit:s,extent:[t.getTime(),n.getTime()]}]}]};return d(o),o}function T(e,t){const n=[],i=a(e,"Field");let s,o=[];for(let u=0;u<i.length;u++){const e=l(i[u],"Identifier"),p=l(i[u],"Description"),c=l(i[u],"Definition"),d=l(i[u],"Abstract"),f=l(i[u],"Title"),h=x(i[u],"NullValue"),b=m(i[u],"AllowedValues"),D=b?v(b):null,y=g(i[u],"1.1.0"),w=[],S=a(i[u],"Axis");for(let n=0;n<S.length;n++){const e=S[n].getAttribute("identifier"),i=l(S[n],"UOM"),a=l(S[n],"DataType"),u=r(S[n],"Key");t&&!e.toLowerCase().includes("band")||(o=u,s=h),w.push({identifier:e,uom:i,dataType:a,values:u,bandNoDataValues:s})}n.push({identifier:e,description:p,definition:c,abstract:d,title:f,supportedInterpolations:y,axis:w,nullValues:h,statistics:D})}return{rangeSet:n,bandNames:o,bandNoDataValues:s,statistics:n[0].statistics}}function R(e,t){if(!t.temporalDomain)return null;const n=e.filter(e=>!e.identifier.toLowerCase().includes("field_1")&&!e.axis.some(e=>e.identifier.includes("band"))),i=[];if(n.length&&n.forEach(e=>{const t=e.axis.map(e=>{const t=e.values.map(t=>{if("ISO8601"===e.uom){return(t=t.trim()).toLowerCase().includes("z")?new Date(t).getTime():new Date(t+"Z").getTime()}return parseFloat(t.trim())}),n=[Math.min.apply(null,t),Math.max.apply(null,t)];return{name:e.identifier.trim(),description:"",field:e.identifier.trim(),unit:e.uom?e.uom.trim():"",hasRegularIntervals:!1,values:t,extent:n}});i.push({name:e.identifier.trim(),description:e.description?.trim()??"",unit:"",dimensions:t,statistics:e.statistics})}),t.temporalDomain){const{begin:e,end:n,values:s,units:a,resolution:o}=t.temporalDomain;i.some(e=>e.dimensions.some(e=>"stdtime"===e.name.toLowerCase()))||i.forEach(t=>{t.dimensions.push({name:"StdTime",description:"",unit:"ISO8601",values:s?.map(e=>e.getTime()),hasRegularIntervals:!s,interval:o,intervalUnit:a,extent:[e.getTime(),n.getTime()]})})}if(i.length){const e={variables:i};return d(e),e}return null}function M(t){const i=m(t,"SpatialDomain"),s=m(i,"GridCRS"),o=l(s,"GridBaseCRS"),r=l(s,"GridOrigin"),u=r?.split(" ").map(e=>parseFloat(e))??[0,0],c=p(s,"GridOffsets"),d=a(i,"BoundingBox");let f,g,h,b;for(let n=0;n<d.length;n++){const t=d[n].getAttribute("crs")?.toLowerCase();if(null!=t)if(t.includes("imagecrs")){const e=p(d[n],"LowerCorner"),t=p(d[n],"UpperCorner");f=t[0]-e[0]+1,g=t[1]-e[1]+1}else if(t.indexOf("epsg")>0){const i=t.split(":");h=parseInt(i[i.length-1],10);const s=p(d[n],"LowerCorner"),a=p(d[n],"UpperCorner");b=new e({xmin:s[0],ymin:s[1],xmax:a[0],ymax:a[1],spatialReference:{wkid:h}})}}const x=f>g,v=b.xmax-b.xmin>b.ymax-b.ymin;let D=!1;n(h)&&(x===v?D=!1:(D=!0,b=new e({xmin:b.ymin,ymin:b.xmin,xmax:b.ymax,ymax:b.xmax,spatialReference:{wkid:h}})));const y={columns:f,rows:g,origin:{x:u[0],y:u[1]},offset:{x:c[0],y:c[c.length-1]},gridBaseCRS:o,envelope:b,useEPSGAxis:D},w=m(t,"temporalDomain")||m(t,"TemporalDomain");return{spatialDomain:y,temporalDomain:w?S(w):null}}function N(e,t){const n=[],i=[],s={supportedFormats:n,supportedCRSs:i,version:"1.1"};let a,o,r=[];for(let c=0;c<e.childNodes.length;c++){const t=e.childNodes[c];if(1!==t.nodeType)continue;const m=u(t).toLowerCase();switch(m){case"title":case"abstract":case"identifier":s[m]=l(t);break;case"supportedformat":{const e=l(t);n.includes(e)||n.push(e)}break;case"supportedcrs":{const e=l(t);i.includes(e)||i.push(e)}break;case"range":{const e=T(t,!!s.domain?.temporalDomain);s.range=e.rangeSet,r=e.bandNames;const{bandNoDataValues:n}=e;n?.length&&(a=D(n)),o=e.statistics}break;case"domain":s.domain=M(t)}}const m=h(s.range[0].supportedInterpolations),{identifier:p,abstract:d,title:f,domain:g,range:b}=s,x={x:Math.abs(g.spatialDomain.offset.x),y:Math.abs(g.spatialDomain.offset.y)},v=R(b,g);v&&(a=b[0].nullValues,1===a?.length&&(a=a[0]));const y=new c({width:g.spatialDomain.columns,height:g.spatialDomain.rows,pixelSize:x,pixelType:"unknown",extent:g.spatialDomain.envelope,spatialReference:g.spatialDomain.envelope.spatialReference,bandCount:r.length||1,noDataValue:a,statistics:o,multidimensionalInfo:v});return{id:p,title:s.title,description:d||f,bandNames:r,rasterInfo:y,supportedFormats:n,supportedInterpolations:m,coverageDescription:s,version:t,useEPSGAxis:g.spatialDomain.useEPSGAxis}}function P(t){const n=m(t,"Envelope")||m(t,"EnvelopeWithTimePeriod"),i=n.getAttribute("srsName"),s=i.slice(i.lastIndexOf("/")+1),a=n.getAttribute("axisLabels").split(" ").map(e=>e.trim()).filter(e=>""!==e.trim()),r=p(n,"lowerCorner"),u=p(n,"upperCorner"),c=!["y","lat","latitude","north","nor","n","b"].includes(a[0].toLowerCase());let d;const f=parseInt(s,10),g=isNaN(f)?null:{wkid:f};d=new e(c?{xmin:r[0],ymin:r[1],xmax:u[0],ymax:u[1],spatialReference:g}:{xmin:r[1],ymin:r[0],xmax:u[1],ymax:u[0],spatialReference:g});const h={mins:r,maxs:u},b=n.getAttribute("uomLabels").trim().split(" ");let x,v;if(o(n,"EnvelopeWithTimePeriod")){x=new Date(l(t,"beginPosition")||l(t,"BeginPosition")),v=new Date(l(t,"endPosition")||l(t,"EndPosition"));const e=b?.findIndex(e=>"oledatetime"===e?.toLowerCase());e>-1&&(b[e]="ISO8601")}return{envelope:d,axisLabels:a,uomLabels:b.length?b:null,envelopeAllDims:h,beginPosition:x,endPosition:v,isEastFirst:c}}function E(e,t){const n=[],i=a(e,"DataRecord"),s=[];let o,r=[];for(let u=0;u<i.length;u++){const e=a(i[u],"field"),c=[];for(let n=0;n<e.length;n++){const i=e[n].getAttribute("name"),a=l(e[n],"description")||"",u=m(e[n],"uom")?.getAttribute("code")||"",d=p(e[n],"interval"),f=x(e[n],"nilValue")?.[0];t&&!i.toLowerCase().includes("band")||(s.push(i),d?.length&&(o=o||[],o.push({min:d[0],max:d[1],avg:-1,stddev:-1})),r.push(f)),c.push({name:i,description:a,uom:u,allowedValues:d,nilValue:f})}n.push(c)}return r.some(e=>null!=e)||(r=null),{rangeType:n,bandNames:s,bandStats:o,bandNoDataValues:r}}function V(e){let t=1,n="";const i=.01;return Math.abs(e-1/24)<1/24*i?n="Hours":Math.abs(e-1)<1*i?n="Days":e<1?(t=Math.round(24*e),n="Hours"):e>28-i&&e<31+i||Math.round(e/30)<12?n="Months":e>365-i&&e<366+i&&(n="Years"),{interval:t,intervalUnit:n}}function A(e,t,n){if(n.axisLabels.length<=2)return null;const s=[];for(let i=0;i<e.length;i++){const t=e[i];for(let e=0;e<t.length;e++)t[e].name.toLowerCase().includes("band")||s.push(t[e])}const a=[];if(s.length){const e=[];for(let s=2;s<n.axisLabels.length;s++){const a=t.uomLabels?.[s]?.trim()??"",o=n.axisLabels[s].toLowerCase().includes("time")||"iso8601"===a.toLowerCase()||"oledatetime"===a.toLowerCase();let l,r;if(o){const e=V(n.offset[s]);l=e.interval,r=e.intervalUnit}else l=n.offset[s],r=a;const u=[];o?(u.push(i(t.envelopeAllDims.mins[s])),u.push(i(t.envelopeAllDims.maxs[s]))):(u.push(t.envelopeAllDims.mins[s]),u.push(t.envelopeAllDims.maxs[s])),e.push({name:n.axisLabels[s].trim(),description:n.axisLabels[s].trim(),unit:o?"ISO8601":a,hasRegularIntervals:!0,extent:u,interval:l,intervalUnit:r})}if(s.forEach(t=>{const{allowedValues:n}=t,i=2===n?.length?[{min:n[0],max:n[1],avg:-1,stddev:-1}]:null;a.push({name:t.name.trim(),description:t.description?.trim()??"",unit:t.uom.trim(),statistics:i,dimensions:[...e]})}),a.length){const e={variables:a};return d(e),e}}return null}function F(e,t){const n=m(e,"RectifiedGrid"),i=p(n,"low"),s=p(n,"high"),o=[];for(let a=0;a<i.length;a++)o.push(s[a]-i[a]+1);const r=l(n,"axisLabels").split(" "),u=p(n,"origin/pos"),c=a(n,"offsetVector"),d=[];for(let a=0;a<c.length;a++){const e=p(c[a]),t=e.findIndex(e=>0!==e);d[t]=e[t]}const f=["y","lat","latitude","north","nor","n","b"];let g=!1;if(t?.length&&r?.length){g=[...t].sort((e,t)=>e<t?-1:1).join(",")===[...r].sort((e,t)=>e<t?-1:1).join(",")}const h=g?r:t;let b,x,v;return f.includes(h[0].toLowerCase())?(b=o[1],x=o[0],v={y:Math.abs(d[0]),x:Math.abs(d[1])}):(b=o[0],x=o[1],v={x:Math.abs(d[0]),y:Math.abs(d[1])}),{columns:b,rows:x,origin:u,offset:d,resolution:v,gridSamples:o,axisLabels:r,hasSameAxisLabelsAsBoundedBy:g}}function O(e){const n=m(e,"EarthObservation");if(!n)return null;const i=m(n,"phenomenonTime"),s=i?S(i):null,a=m(n,"phenomenonTime"),o=a?S(a):null,r=l(n,"featureOfInterest/Footprint/multiExtentOf/MultiSurface/surfaceMembers/Polygon/exterior/LinearRing/posList");let u=null;if(r){const e=r.split(" ").map(e=>e.trim()).filter(e=>null!=e&&""!==e).map(Number);if(e.length){const n=[];for(let t=0;t<e.length/2;t+=2)n.push(e[t],e[t+1]);u=new t({rings:[[n]]})}}return{observation:{phenomenonTime:s,resultTime:o,footprint:u,identifier:l(e,"metaDataProperty/EarthObservationMetaData/identifier"),acquisitionType:l(e,"metaDataProperty/EarthObservationMetaData/acquisitionType"),status:l(e,"metaDataProperty/EarthObservationMetaData/status")}}}function B(e){const t={version:"2.0"};let n,i,s=[];for(let c=0;c<e.childNodes.length;c++){const a=e.childNodes[c];if(1===a.nodeType)if(o(a,"coverageId"))t.coverageId=l(a);else if(o(a,"ServiceParameters"))t.serviceParameters={supportedFormats:r(a,"nativeFormat")};else if(o(a,"boundedBy"))t.boundedBy=P(a);else if(o(a,"rangeType")){const e=E(a,t.boundedBy?.axisLabels.length>2||t.domainSet?.axisLabels.length>2);t.rangeType=e.rangeType,s=e.bandNames,n=e.bandStats;const{bandNoDataValues:o}=e;o?.length&&(i=D(o))}else if(o(a,"domainSet"))t.domainSet=F(a,t.boundedBy?.axisLabels);else if(o(a,"metadata")){const e=m(a,"EOMetadata");t.eoMetadata=e?O(e):null}}const{coverageId:a,boundedBy:u,domainSet:p,rangeType:d,serviceParameters:f}=t,g=A(d,u,p);!n&&g&&(n=g?.variables[0].statistics),null!=g&&(i=d[0][0].nilValue);return{id:a,title:a,description:a,bandNames:s,rasterInfo:new c({width:p.columns,height:p.rows,pixelSize:p.resolution,pixelType:"unknown",extent:u.envelope,spatialReference:u.envelope.spatialReference,bandCount:s.length||1,statistics:n,noDataValue:i,multidimensionalInfo:g}),supportedFormats:f.supportedFormats,coverageDescription:t,version:"2.0.1",useEPSGAxis:!1}}function k(e,t){let n=null;if("string"==typeof e){n=(new DOMParser).parseFromString(e,"text/xml")}else n=e;if("1.0.0"===t){return a(n,"CoverageOffering").map(e=>L(e))}const i=a(n,"CoverageDescription");return"1.1.0"===t||"1.1.1"===t||"1.1.2"===t?i.map(e=>N(e,t)):i.map(e=>B(e))}export{k as parseCoverages,h as standardizeInterpolations};