UNPKG

@arcgis/core

Version:

ArcGIS Maps SDK for JavaScript: A complete 2D and 3D mapping and data visualization API

6 lines (5 loc) • 15.5 kB
/* All material copyright ESRI, All Rights Reserved, unless otherwise specified. See https://js.arcgis.com/4.33/esri/copyright.txt for details. */ import e from"../../../geometry/Extent.js";import t from"../../../geometry/Polygon.js";import{isAxesOrderReversedForWkid as n}from"../../ogc/crsUtils.js";import i from"../RasterInfo.js";import{convertOleDateTimeToEpoch as s,getDimensionValues as a}from"./multidimensionalUtils.js";import{getElements as o,isSameTagIgnoreNS as l,getElementValue as r,getElementValues as u,getNodeNameIgnoreNS as m,getElement as p,getSpaceDelimitedNumericValues as c}from"./xmlUtilities.js";function d(e){e.variables.forEach((e=>e.dimensions.forEach((e=>e.values??=a(e)))))}function f(e){return{requestResponseCRSs:u(e,"requestResponseCRSs").map((e=>e.split(":")[1])),nativeCRSs:u(e,"nativeCRSs").map((e=>e.split(":")[1]))}}function g(e,t){const n=u(e,"1.0.0"===t?"interpolationMethod":"InterpolationMethod"),i="1.0.0"===t?e.getAttribute("default"):r(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=o(t,"pos"),i=c(n[0]),s=c(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=u(e,t);return n?.length&&""!==n[0]&&!isNaN(Number(n[0]))?n.map((e=>Number(e))):null}function v(e){const t=c(e,"MinimumValue"),n=c(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=o(e,"RangeSet");let i=[];for(let s=0;s<n.length;s++){const e=r(n[s],"name"),a=r(n[s],"label"),l=[],m=x(n[s],"nullValues/singleValue"),p=o(n[s],"AxisDescription");for(let t=0;t<p.length;t++){const e=r(p[t],"name"),n=r(p[t],"label"),s=u(p[t],"singleValue");if(0===s.length){const e=r(p[t],"min"),n=r(p[t],"max"),i=Number(r(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),l.push({name:e,label:n,values:s})}t.push({name:e,label:a,nullValues:m,axis:l})}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=o(e,"timeposition");if(t.length>0){const e=[];for(let n=0;n<t.length;n++)e.push(new Date(r(t[n])));return{begin:e[0],end:e[e.length-1],values:e}}const n=p(e,"timePeriod")||p(e,"TimePeriod");if(n){return{begin:new Date(r(n,"beginPosition")||r(n,"BeginPosition")),end:new Date(r(n,"endPosition")||r(n,"EndPosition")),...w(r(n,"timeResolution")||r(n,"TimeResolution"))}}return null}function I(t){const n=p(t,"spatialDomain"),i=p(n,"Envelope")||p(n,"EnvelopeWithTimePeriod"),s=i.getAttribute("srsName").split(":"),a=s[s.length-1],l=o(i,"pos"),u=c(l[0]),m=c(l[1]),d=parseInt(a,10),f=isNaN(d)?null:{wkid:d},g=new e({xmin:u[0],ymin:u[1],xmax:m[0],ymax:m[1],spatialReference:f}),h=p(n,"RectifiedGrid"),b=r(h,"low").split(" "),x=r(h,"high").split(" "),v=parseInt(x[0],10)-parseInt(b[0],10)+1,D=parseInt(x[1],10)-parseInt(b[1],10)+1,y=c(n,"origin/pos"),w=o(n,"offsetVector"),I={envelope:g,columns:v,rows:D,offset:{x:parseFloat(r(w[0]).split(" ")[0]),y:parseFloat(r(w[1]).split(" ")[1])},origin:{x:y[0],y:y[1]}},L=p(t,"temporalDomain")||p(t,"TemporalDomain");return{spatialDomain:I,temporalDomain:L?S(L):null}}function L(e){const t={version:"1.0"};let n,s=[];for(let i=0;i<e.childNodes.length;i++){const a=e.childNodes[i];if(1===a.nodeType)if(l(a,"description"))t.description=r(a);else if(l(a,"name"))t.name=r(a);else if(l(a,"label"))t.label=r(a);else if(l(a,"supportedFormats"))t.supportedFormats=u(a,"formats");else if(l(a,"supportedCRSs"))t.supportedCRSs=f(a);else if(l(a,"supportedInterpolations"))t.supportedInterpolations=g(a,"1.0.0");else if(l(a,"lonLatEnvelope"))t.lonLatEnvelope=b(a);else if(l(a,"rangeSet")){const e=y(a);t.rangeSet=e.rangeSet,s=e.bandNames;const i=e.rangeSet[0].nullValues;i?.length&&(n=D(i))}else l(a,"domainSet")&&(t.domainSet=I(a))}const a=h(t.supportedInterpolations),{name:o,description:m,label:p,lonLatEnvelope:c,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 i({width:x.columns,height:x.rows,pixelSize:v,pixelType:"unknown",extent:x.envelope,spatialReference:x.envelope.spatialReference,bandCount:s.length||1,noDataValue:n,multidimensionalInfo:w});return{id:o,title:t.name,description:m||p,lonLatEnvelope:c,rasterInfo:S,bandNames:s,supportedFormats:d,supportedInterpolations:a,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=o(e,"Field");let s,a=[];for(let l=0;l<i.length;l++){const e=r(i[l],"Identifier"),m=r(i[l],"Description"),c=r(i[l],"Definition"),d=r(i[l],"Abstract"),f=r(i[l],"Title"),h=x(i[l],"NullValue"),b=p(i[l],"AllowedValues"),D=b?v(b):null,y=g(i[l],"1.1.0"),w=[],S=o(i[l],"Axis");for(let n=0;n<S.length;n++){const e=S[n].getAttribute("identifier"),i=r(S[n],"UOM"),o=r(S[n],"DataType"),l=u(S[n],"Key");t&&!e.toLowerCase().includes("band")||(a=l,s=h),w.push({identifier:e,uom:i,dataType:o,values:l,bandNoDataValues:s})}n.push({identifier:e,description:m,definition:c,abstract:d,title:f,supportedInterpolations:y,axis:w,nullValues:h,statistics:D})}return{rangeSet:n,bandNames:a,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=p(t,"SpatialDomain"),s=p(i,"GridCRS"),a=r(s,"GridBaseCRS"),l=r(s,"GridOrigin"),u=l?.split(" ").map((e=>parseFloat(e)))??[0,0],m=c(s,"GridOffsets"),d=o(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=c(d[n],"LowerCorner"),t=c(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=c(d[n],"LowerCorner"),a=c(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:m[0],y:m[m.length-1]},gridBaseCRS:a,envelope:b,useEPSGAxis:D},w=p(t,"temporalDomain")||p(t,"TemporalDomain");return{spatialDomain:y,temporalDomain:w?S(w):null}}function N(e,t){const n=[],s=[],a={supportedFormats:n,supportedCRSs:s,version:"1.1"};let o,l,u=[];for(let i=0;i<e.childNodes.length;i++){const t=e.childNodes[i];if(1!==t.nodeType)continue;const p=m(t).toLowerCase();switch(p){case"title":case"abstract":case"identifier":a[p]=r(t);break;case"supportedformat":{const e=r(t);n.includes(e)||n.push(e)}break;case"supportedcrs":{const e=r(t);s.includes(e)||s.push(e)}break;case"range":{const e=T(t,!!a.domain?.temporalDomain);a.range=e.rangeSet,u=e.bandNames;const{bandNoDataValues:n}=e;n?.length&&(o=D(n)),l=e.statistics}break;case"domain":a.domain=M(t)}}const p=h(a.range[0].supportedInterpolations),{identifier:c,abstract:d,title:f,domain:g,range:b}=a,x={x:Math.abs(g.spatialDomain.offset.x),y:Math.abs(g.spatialDomain.offset.y)},v=R(b,g);v&&(o=b[0].nullValues,1===o?.length&&(o=o[0]));const y=new i({width:g.spatialDomain.columns,height:g.spatialDomain.rows,pixelSize:x,pixelType:"unknown",extent:g.spatialDomain.envelope,spatialReference:g.spatialDomain.envelope.spatialReference,bandCount:u.length||1,noDataValue:o,statistics:l,multidimensionalInfo:v});return{id:c,title:a.title,description:d||f,bandNames:u,rasterInfo:y,supportedFormats:n,supportedInterpolations:p,coverageDescription:a,version:t,useEPSGAxis:g.spatialDomain.useEPSGAxis}}function P(t){const n=p(t,"Envelope")||p(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())),o=c(n,"lowerCorner"),u=c(n,"upperCorner"),m=!["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(m?{xmin:o[0],ymin:o[1],xmax:u[0],ymax:u[1],spatialReference:g}:{xmin:o[1],ymin:o[0],xmax:u[1],ymax:u[0],spatialReference:g});const h={mins:o,maxs:u},b=n.getAttribute("uomLabels").trim().split(" ");let x,v;if(l(n,"EnvelopeWithTimePeriod")){x=new Date(r(t,"beginPosition")||r(t,"BeginPosition")),v=new Date(r(t,"endPosition")||r(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:m}}function E(e,t){const n=[],i=o(e,"DataRecord"),s=[];let a,l=[];for(let u=0;u<i.length;u++){const e=o(i[u],"field"),m=[];for(let n=0;n<e.length;n++){const i=e[n].getAttribute("name"),o=r(e[n],"description")||"",u=p(e[n],"uom")?.getAttribute("code")||"",d=c(e[n],"interval"),f=x(e[n],"nilValue")?.[0];t&&!i.toLowerCase().includes("band")||(s.push(i),d?.length&&(a=a||[],a.push({min:d[0],max:d[1],avg:-1,stddev:-1})),l.push(f)),m.push({name:i,description:o,uom:u,allowedValues:d,nilValue:f})}n.push(m)}return l.some((e=>null!=e))||(l=null),{rangeType:n,bandNames:s,bandStats:a,bandNoDataValues:l}}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 i=[];for(let s=0;s<e.length;s++){const t=e[s];for(let e=0;e<t.length;e++)t[e].name.toLowerCase().includes("band")||i.push(t[e])}const a=[];if(i.length){const e=[];for(let i=2;i<n.axisLabels.length;i++){const a=t.uomLabels?.[i]?.trim()??"",o=n.axisLabels[i].toLowerCase().includes("time")||"iso8601"===a.toLowerCase()||"oledatetime"===a.toLowerCase();let l,r;if(o){const e=V(n.offset[i]);l=e.interval,r=e.intervalUnit}else l=n.offset[i],r=a;const u=[];o?(u.push(s(t.envelopeAllDims.mins[i])),u.push(s(t.envelopeAllDims.maxs[i]))):(u.push(t.envelopeAllDims.mins[i]),u.push(t.envelopeAllDims.maxs[i])),e.push({name:n.axisLabels[i].trim(),description:n.axisLabels[i].trim(),unit:o?"ISO8601":a,hasRegularIntervals:!0,extent:u,interval:l,intervalUnit:r})}if(i.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=p(e,"RectifiedGrid"),i=c(n,"low"),s=c(n,"high"),a=[];for(let o=0;o<i.length;o++)a.push(s[o]-i[o]+1);const l=r(n,"axisLabels").split(" "),u=c(n,"origin/pos"),m=o(n,"offsetVector"),d=[];for(let o=0;o<m.length;o++){const e=c(m[o]),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&&l?.length){g=[...t].sort(((e,t)=>e<t?-1:1)).join(",")===[...l].sort(((e,t)=>e<t?-1:1)).join(",")}const h=g?l:t;let b,x,v;return f.includes(h[0].toLowerCase())?(b=a[1],x=a[0],v={y:Math.abs(d[0]),x:Math.abs(d[1])}):(b=a[0],x=a[1],v={x:Math.abs(d[0]),y:Math.abs(d[1])}),{columns:b,rows:x,origin:u,offset:d,resolution:v,gridSamples:a,axisLabels:l,hasSameAxisLabelsAsBoundedBy:g}}function O(e){const n=p(e,"EarthObservation");if(!n)return null;const i=p(n,"phenomenonTime"),s=i?S(i):null,a=p(n,"phenomenonTime"),o=a?S(a):null,l=r(n,"featureOfInterest/Footprint/multiExtentOf/MultiSurface/surfaceMembers/Polygon/exterior/LinearRing/posList");let u=null;if(l){const e=l.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:r(e,"metaDataProperty/EarthObservationMetaData/identifier"),acquisitionType:r(e,"metaDataProperty/EarthObservationMetaData/acquisitionType"),status:r(e,"metaDataProperty/EarthObservationMetaData/status")}}}function B(e){const t={version:"2.0"};let n,s,a=[];for(let i=0;i<e.childNodes.length;i++){const o=e.childNodes[i];if(1===o.nodeType)if(l(o,"coverageId"))t.coverageId=r(o);else if(l(o,"ServiceParameters"))t.serviceParameters={supportedFormats:u(o,"nativeFormat")};else if(l(o,"boundedBy"))t.boundedBy=P(o);else if(l(o,"rangeType")){const e=E(o,t.boundedBy?.axisLabels.length>2||t.domainSet?.axisLabels.length>2);t.rangeType=e.rangeType,a=e.bandNames,n=e.bandStats;const{bandNoDataValues:i}=e;i?.length&&(s=D(i))}else if(l(o,"domainSet"))t.domainSet=F(o,t.boundedBy?.axisLabels);else if(l(o,"metadata")){const e=p(o,"EOMetadata");t.eoMetadata=e?O(e):null}}const{coverageId:o,boundedBy:m,domainSet:c,rangeType:d,serviceParameters:f}=t,g=A(d,m,c);!n&&g&&(n=g?.variables[0].statistics),null!=g&&(s=d[0][0].nilValue);return{id:o,title:o,description:o,bandNames:a,rasterInfo:new i({width:c.columns,height:c.rows,pixelSize:c.resolution,pixelType:"unknown",extent:m.envelope,spatialReference:m.envelope.spatialReference,bandCount:a.length||1,statistics:n,noDataValue:s,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 o(n,"CoverageOffering").map((e=>L(e)))}const i=o(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};