UNPKG

@arcgis/core

Version:

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

6 lines (5 loc) • 14.4 kB
/* All material copyright ESRI, All Rights Reserved, unless otherwise specified. See https://js.arcgis.com/4.32/esri/copyright.txt for details. */ import{_ as e}from"../../chunks/tslib.es6.js";import t from"../../core/JSONSupport.js";import r from"../../core/Logger.js";import{property as s}from"../../core/accessorSupport/decorators/property.js";import"../../core/has.js";import"../../core/RandomLCG.js";import{subclass as a}from"../../core/accessorSupport/decorators/subclass.js";import o from"../../layers/support/RasterInfo.js";import{colorize as n,remapColor as i,lookupPixels as l,createColormapLUT as u,isValidPixelBlock as c}from"../../layers/support/rasterFunctions/pixelUtils.js";import{stretch as p,getStretchCutoff as d,createStretchLUT as h,computeGammaValues as m,createHistogramEqualizationLUT as f}from"../../layers/support/rasterFunctions/stretchUtils.js";import{hillshade as y,tintHillshade as b,calculateHillshadeParams as g}from"../../layers/support/rasterFunctions/surfaceUtils.js";import{convertColorRampToColormap as S,createHsvMap as k}from"./colorRampUtils.js";import{isUVRendererSupported as x,isColormapSupportedByWebGL as I,isColormapRendererSupported as R,isShadedReliefRendererSupported as C}from"./rasterRendererChecks.js";let L=class extends t{constructor(e){super(e)}bind(){const{rendererJSON:e}=this;if(!e)return{success:!1};let t;switch(this.lookup={rendererJSON:{}},e.type){case"uniqueValue":t=this._updateUVRenderer(e);break;case"rasterColormap":t=this._updateColormapRenderer(e);break;case"rasterStretch":t=this._updateStretchRenderer(e);break;case"classBreaks":t=this._updateClassBreaksRenderer(e);break;case"rasterShadedRelief":t=this._updateShadedReliefRenderer(e);break;case"vectorField":t=this._updateVectorFieldRenderer();break;case"flowRenderer":t=this._updateFlowRenderer()}return t}symbolize(e){let t=e?.pixelBlock;if(!v(t))return t;if(e.simpleStretchParams&&"rasterStretch"===this.rendererJSON.type)return this.simpleStretch(t,e.simpleStretchParams);try{let r;switch(t.pixels.length>3&&(t=t.extractBands(e.bandIds??[0,1,2])),this.rendererJSON.type){case"uniqueValue":case"rasterColormap":r=this._symbolizeColormap(t);break;case"classBreaks":r=this._symbolizeClassBreaks(t);break;case"rasterStretch":r=this._symbolizeStretch(t,e.bandIds);break;case"rasterShadedRelief":{const s=e.extent,a=s.spatialReference.isGeographic,o={x:(s.xmax-s.xmin)/t.width,y:(s.ymax-s.ymin)/t.height};r=this._symbolizeShadedRelief(t,{isGCS:a,resolution:o});break}}return r}catch(s){return r.getLogger(this).error("symbolize",s.message),t}}simpleStretch(e,t){if(!v(e))return e;try{return e.pixels.length>3&&(e=e.extractBands([0,1,2])),p(e,{...t,isRenderer:!0})}catch(s){return r.getLogger(this).error("symbolize",s.message),e}}generateWebGLParameters(e){if(["uniqueValue","rasterColormap","classBreaks"].includes(this.rendererJSON.type)){const{indexedColormap:e,offset:t}=this.lookup.colormapLut||{};return{colormap:e,colormapOffset:t,isClassBreaks:"classBreaks"===this.rendererJSON.type,type:"lut"}}const{pixelBlock:t,isGCS:r,resolution:s,bandIds:a}=e,{rendererJSON:o}=this;return"rasterStretch"===o.type?this._generateStretchWebGLParams(t,o,a):"rasterShadedRelief"===o.type?this._generateShadedReliefWebGLParams(o,r,s??void 0):"vectorField"===o.type?this._generateVectorFieldWebGLParams(o):null}_isLUTChanged(e){if(!this.lookup||!this.lookup.rendererJSON)return!0;if("colorRamp"in this.rendererJSON){const t=this.rendererJSON.colorRamp;return e?JSON.stringify(t)!==JSON.stringify(this.lookup.rendererJSON.colorRamp):(this.rendererJSON,this.lookup.rendererJSON,JSON.stringify(this.rendererJSON)!==JSON.stringify(this.lookup.rendererJSON))}return JSON.stringify(this.rendererJSON)!==JSON.stringify(this.lookup.rendererJSON)}_symbolizeColormap(e){if(this._isLUTChanged()){if(!this.bind().success)return e}return n(e,this.lookup.colormapLut)}_symbolizeClassBreaks(e){const{canUseIndexedLUT:t}=this._analyzeClassBreaks(this.rendererJSON);if(this._isLUTChanged()){if(!this.bind().success)return e}return t?n(e,this.lookup.colormapLut):i(e,this.lookup.remapLut??[])}_symbolizeStretch(e,t){const{rasterInfo:r}=this,{pixelType:s,bandCount:a}=r,o=this.rendererJSON,i=["u8","u16","s8","s16"].includes(s);let u,c;const{dra:m}=o,{gamma:f}=this.lookup;if("histogramEqualization"===o.stretchType){const s=m?null:this.lookup?.histogramLut,a=d(o,{rasterInfo:r,pixelBlock:e,bandIds:t,returnHistogramLut:!s}),n=p(e,{...a,gamma:f,isRenderer:!0});c=l(n,{lut:m?a.histogramLut:s,offset:0})}else if(i){if(m){const a=d(o,{rasterInfo:r,pixelBlock:e,bandIds:t});u=h({pixelType:s,...a,gamma:f,rounding:"floor"})}else if(this._isLUTChanged()){if(!this.bind().success)return e;u=this.lookup?this.lookup.stretchLut:null}else u=this.lookup?this.lookup.stretchLut:null;if(!u)return e;a>1&&null!=t&&t.length===e?.pixels.length&&u?.lut.length===a&&(u={lut:t.map((e=>u.lut[e])),offset:u.offset}),c=l(e,u)}else{const s=d(o,{rasterInfo:r,pixelBlock:e,bandIds:t});c=p(e,{...s,gamma:f,isRenderer:!0})}if(o.colorRamp){if(this._isLUTChanged(!0)){if(!this.bind().success)return e}c=n(c,this.lookup?.colormapLut)}return c}_symbolizeShadedRelief(e,t){const r=this.rendererJSON,s={...r,...t},a=y(e,s);if(!r.colorRamp)return a;let o;if(this._isLUTChanged(!0)){if(!this.bind().success)return a;o=this.lookup?this.lookup.hsvMap:null}else o=this.lookup?this.lookup.hsvMap:null;if(!o)return a;const n=this.rasterInfo.statistics?.[0]??{min:0,max:8e3};return b(a,e,o,n),a}_isVectorFieldData(){const{bandCount:e,dataType:t}=this.rasterInfo;return 2===e&&("vector-magdir"===t||"vector-uv"===t)}_updateVectorFieldRenderer(){return this._isVectorFieldData()?{success:!0}:{success:!1,error:`Unsupported data type "${this.rasterInfo.dataType}"; VectorFieldRenderer only supports "vector-magdir" and "vector-uv".`}}_updateFlowRenderer(){return this._isVectorFieldData()?{success:!0}:{success:!1,error:`Unsupported data type "${this.rasterInfo.dataType}"; FlowRenderer only supports "vector-magdir" and "vector-uv".`}}_updateUVRenderer(e){const{bandCount:t,attributeTable:r,pixelType:s}=this.rasterInfo,a=e.field1;if(!a)return{success:!1,error:"Unsupported renderer; missing UniqueValueRenderer.field."};const o=e.defaultSymbol,n=1===t&&["u8","s8"].includes(s);if(!x(this.rasterInfo,a)&&!n)return{success:!1,error:"Unsupported data; UniqueValueRenderer is only supported on single band data with a valid raster attribute table."};const i=[];if(null!=r){const t=r.fields.find((e=>"value"===e.name.toLowerCase()));if(!t)return{success:!1,error:"Unsupported data; the data's raster attribute table does not have a value field."};r.features.forEach((r=>{const s=e.uniqueValueInfos?.find((e=>String(e.value)===String(r.attributes[a]))),n=s?.symbol?.color;n?i.push([r.attributes[t.name]].concat(n)):o&&i.push([r.attributes[t.name]].concat(o.color))}))}else{if("value"!==a.toLowerCase())return{success:!1,error:'Unsupported renderer; UniqueValueRenderer.field must be "Value" when raster attribute table is not available.'};e.uniqueValueInfos?.forEach((e=>{const t=e?.symbol?.color;t?i.push([parseInt(""+e.value,10)].concat(t)):o&&i.push([parseInt(""+e.value,10)].concat(o?.color))}))}if(0===i.length)return{success:!1,error:"Invalid UniqueValueRenderer. Cannot find matching records in the raster attribute table."};const l=u({colormap:i});return this.lookup={rendererJSON:e,colormapLut:l},this.canRenderInWebGL=I(l?.indexedColormap),{success:!0}}_updateColormapRenderer(e){if(!R(this.rasterInfo))return{success:!1,error:"Unsupported data; the data source does not have a colormap."};const t=e.colormapInfos.map((e=>[e.value].concat(e.color))).sort(((e,t)=>e[0]-t[0]));if(!t||0===t.length)return{success:!1,error:"Unsupported renderer; ColormapRenderer must have meaningful colormapInfos."};const r=u({colormap:t});return this.lookup={rendererJSON:e,colormapLut:r},this.canRenderInWebGL=I(r?.indexedColormap),{success:!0}}_updateShadedReliefRenderer(e){if(!C(this.rasterInfo))return{success:!1,error:`Unsupported data type "${this.rasterInfo.dataType}"; ShadedReliefRenderer only supports "elevation", or single band float/s16 data.`};if(e.colorRamp){const t=S(e.colorRamp,{interpolateAlpha:!0}),r=u({colormap:t}),s=k(r.indexedColormap);this.lookup={rendererJSON:e,colormapLut:r,hsvMap:s}}else this.lookup=null;return this.canRenderInWebGL=!0,{success:!0}}_analyzeClassBreaks(e){const{attributeTable:t,pixelType:r}=this.rasterInfo,s=null!=t?t.fields.find((e=>"value"===e.name.toLowerCase())):null,a=null!=t?t.fields.find((t=>t.name.toLowerCase()===e.field.toLowerCase())):null,o=null!=s&&null!==a;return{canUseIndexedLUT:["u8","u16","s8","s16"].includes(r)||o,tableValueField:s,tableBreakField:a}}_updateClassBreaksRenderer(e){const{attributeTable:t}=this.rasterInfo,{canUseIndexedLUT:r,tableValueField:s,tableBreakField:a}=this._analyzeClassBreaks(e),o=e.classBreakInfos;if(!o?.length)return{success:!1,error:"Unsupported renderer; missing or invalid ClassBreaksRenderer.classBreakInfos."};const n=o.sort(((e,t)=>e.classMaxValue-t.classMaxValue)),i=n[n.length-1];let l=e.minValue;if(!r){const t=[];for(let e=0;e<n.length;e++)t.push({value:n[e].classMinValue??l,mappedColor:n[e].symbol.color}),l=n[e].classMaxValue;return t.push({value:i.classMaxValue,mappedColor:i.symbol.color}),this.lookup={rendererJSON:e,remapLut:t},this.canRenderInWebGL=!1,{success:!0}}const c=[];if(null!=t&&null!=s&&null!==a&&s!==a){const r=s.name,o=a.name,i=n[n.length-1],{classMaxValue:u}=i;l=e.minValue;for(const e of t.features){const t=e.attributes[r],s=e.attributes[o],a=s===u?i:s<l?null:n.find((({classMaxValue:e})=>e>s));a&&c.push([t].concat(a.symbol.color))}}else{l=Math.floor(e.minValue);for(let e=0;e<n.length;e++){const t=n[e];for(let e=l;e<t.classMaxValue;e++)c.push([e].concat(t.symbol.color));l=Math.ceil(t.classMaxValue)}i.classMaxValue===l&&c.push([i.classMaxValue].concat(i.symbol.color))}const p=u({colormap:c,fillUnspecified:!1});return this.lookup={rendererJSON:e,colormapLut:p},this.canRenderInWebGL=I(p?.indexedColormap),{success:!0}}_updateStretchRenderer(e){let{stretchType:t,dra:r}=e;if(!("none"===t||e.statistics?.length||V(this.rasterInfo.statistics)||r))return{success:!1,error:"Unsupported renderer; StretchRenderer.statistics is required when dynamic range adjustment is not used."};const s=e.histograms||this.rasterInfo.histograms;!O(e.stretchType)||s?.length||r||(t="minMax");const{computeGamma:a,useGamma:o,colorRamp:n}=e;let{gamma:i}=e;if(o&&a&&!i?.length){const t=e.statistics?.length?e.statistics:this.rasterInfo.statistics;i=m(this.rasterInfo.pixelType,t)}const l=this.rasterInfo.pixelType,c=!r&&["u8","u16","s8","s16"].includes(l);if("histogramEqualization"===t){const t=s.map((e=>f(e)));this.lookup={rendererJSON:e,histogramLut:t}}else if(c){const t=d(e,{rasterInfo:this.rasterInfo}),r=h({pixelType:l,...t,gamma:o?i:null,rounding:"floor"});this.lookup={rendererJSON:e,stretchLut:r}}if(n&&!T(n)){const t=S(n,{interpolateAlpha:!0});this.lookup||(this.lookup={rendererJSON:e}),this.lookup.colormapLut=u({colormap:t}),this.lookup.rendererJSON=e}return this.lookup.gamma=o&&i?.length?i:null,this.canRenderInWebGL=!0,{success:!0}}_generateStretchWebGLParams(e,t,r){let s=null,a=null;const o=this.lookup?.colormapLut;t.colorRamp&&o&&(s=o.indexedColormap,a=o.offset),"histogramEqualization"===t.stretchType&&(t={...t,stretchType:"minMax"});const{gamma:n}=this.lookup,i=!(!t.useGamma||!n?.some((e=>1!==e))),{minCutOff:l,maxCutOff:u,minOutput:c,maxOutput:p}=d(t,{rasterInfo:this.rasterInfo,pixelBlock:e,bandIds:r});let h=0;null!=e&&(h=e.getPlaneCount(),2===h&&((e=e.clone()).statistics=[e.statistics[0]],e.pixels=[e.pixels[0]]));const{bandCount:m}=this.rasterInfo,f=Math.min(3,r?.length||h||m,m),y=s||i?1:255,b=new Float32Array(f);if(i&&n)for(let d=0;d<f;d++)n[d]>1?n[d]>2?b[d]=6.5+(n[d]-2)**2.5:b[d]=6.5+100*(2-n[d])**4:b[d]=1;1===l.length&&(l[2]=l[1]=l[0]),1===u.length&&(u[2]=u[1]=u[0]);const g=i&&n?[n[0],n[1]??n[0],n[2]??n[0]]:[1,1,1],S=i?[b[0],b[1]??b[0],b[2]??b[0]]:[1,1,1],k=u.map(((e,t)=>u[t]===l[t]?0:(p-c)/(u[t]-l[t])/y));return{bandCount:f,minOutput:c/y,maxOutput:p/y,minCutOff:l,maxCutOff:u,factor:k,useGamma:i,gamma:g,gammaCorrection:S,colormap:s,colormapOffset:a,stretchType:t.stretchType,type:"stretch"}}_generateShadedReliefWebGLParams(e,t=!1,r={x:0,y:0}){let s=null,a=null;const o=this.lookup?.colormapLut;e.colorRamp&&o&&(s=o.indexedColormap,a=o.offset);const n={...e,isGCS:t,resolution:r},i=g(n),l=this.rasterInfo.statistics?.[0];return{...i,minValue:l?.min??0,maxValue:l?.max??8e3,hillshadeType:"traditional"===e.hillshadeType?0:1,type:"hillshade",colormap:s,colormapOffset:a}}_generateVectorFieldWebGLParams(e){const{style:t,inputUnit:r,outputUnit:s,visualVariables:a,symbolTileSize:o,flowRepresentation:n}=e;let i;const l=this.rasterInfo.statistics?.[0].min??0,u=this.rasterInfo.statistics?.[0].max??50,c=a?.find((e=>"sizeInfo"===e.type))??{type:"sizeInfo",field:"Magnitude",maxDataValue:u,maxSize:.8*o,minDataValue:l,minSize:.2*o},p=c.minDataValue??l,d=c.maxDataValue??u,h=null!=c.maxSize&&null!=c.minSize?[c.minSize/o,c.maxSize/o]:[.2,.8];if("wind_speed"===t){const e=(h[0]+h[1])/2;h[0]=h[1]=e}const m=null!=p&&null!=d?[p,d]:null;if("classified_arrow"===t)if(null!=p&&null!=d&&null!=c){i=[];const e=(c.maxDataValue-c.minDataValue)/5;for(let t=0;t<6;t++)i.push(c.minDataValue+e*t)}else i=[0,1e-6,3.5,7,10.5,14];const f="flow_to"===n===("ocean_current_kn"===t||"ocean_current_m"===t)?0:Math.PI,y=a?.find((e=>"rotationInfo"===e.type));return{breakValues:i,dataRange:m,inputUnit:r,outputUnit:s,symbolTileSize:o,symbolPercentRange:h,style:t||"single_arrow",rotation:f,rotationType:this.rasterInfo.storageInfo?.tileInfo&&"vector-uv"===this.rasterInfo.dataType?"geographic":y?.rotationType||e.rotationType,type:"vectorField"}}};e([s({json:{write:!0}})],L.prototype,"rendererJSON",void 0),e([s({type:o,json:{write:!0}})],L.prototype,"rasterInfo",void 0),e([s({json:{write:!0}})],L.prototype,"lookup",void 0),e([s()],L.prototype,"canRenderInWebGL",void 0),L=e([a("esri.renderers.support.RasterSymbolizer")],L);const _=L;function O(e){return"percentClip"===e||"histogramEqualization"===e}function V(e){return null!=e&&e.length>0&&null!=e[0].min&&null!=e[0].max}function v(e){return c(e)&&0!==e.validPixelCount}function T(e){return"algorithmic"===e.type&&["0,0,0,255","0,0,0"].includes(e.fromColor.join(","))&&["255,255,255,255","255,255,255"].includes(e.toColor.join(","))}export{_ as default};