@doegis/core
Version:
DOE GIS API
3 lines (1 loc) • 14.4 kB
JavaScript
import{_ as e}from"../../chunks/tslib.es6.js";import{toHSV as t}from"../../core/colorUtils.js";import{JSONSupport as r}from"../../core/JSONSupport.js";import s from"../../core/Logger.js";import{unwrap as o,isSome as a,isNone as n}from"../../core/maybe.js";import{property as i}from"../../core/accessorSupport/decorators/property.js";import"../../core/accessorSupport/ensureType.js";import"../../core/arrayUtils.js";import{subclass as l}from"../../core/accessorSupport/decorators/subclass.js";import u from"../../layers/support/RasterInfo.js";import{extractBands as c,colorize as p,remapColor as d,lookupPixels as h,createColormapLUT as m,isValidPixelBlock as f}from"../../layers/support/rasterFunctions/pixelUtils.js";import{stretch as y,getStretchCutoff as b,createStretchLUT as g,computeGammaValues as S,createHistogramEqualizationLUT as k}from"../../layers/support/rasterFunctions/stretchUtils.js";import{hillshade as R,tintHillshade as x,calculateHillshadeParams as I}from"../../layers/support/rasterFunctions/surfaceUtils.js";import{convertColorRampToColormap as C}from"./colorRampUtils.js";function L(e,t){const{attributeTable:r,bandCount:s}=e;if(n(r)||s>1)return!1;if(t){if(null==r.fields.find((e=>e.name.toLowerCase()===t.toLowerCase())))return!1}return!0}function _(e){const{bandCount:t,dataType:r,pixelType:s}=e;return"elevation"===r||"generic"===r&&1===t&&("s16"===s||"f32"===s||"f64"===s)}function V(e){const{bandCount:t,colormap:r}=e;return a(r)&&r.length>0&&1===t}let v=class extends r{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&&e.pixelBlock;if(!O(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=c(t,[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,o=s.spatialReference.isGeographic,a={x:(s.xmax-s.xmin)/t.width,y:(s.ymax-s.ymin)/t.height};r=this._symbolizeShadedRelief(t,{isGCS:o,resolution:a});break}}return r}catch(r){return s.getLogger(this.declaredClass).error("symbolize",r.message),t}}simpleStretch(e,t){if(!O(e))return e;try{return e.pixels.length>3&&(e=c(e,[0,1,2])),y(e,{...t,isRenderer:!0})}catch(r){return s.getLogger(this.declaredClass).error("symbolize",r.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,type:"lut"}}const{pixelBlock:t,isGCS:r,resolution:s,bandIds:o}=e,{rendererJSON:a}=this;return"rasterStretch"===a.type?this._generateStretchWebGLParams(t,a,o):"rasterShadedRelief"===a.type?this._generateShadedReliefWebGLParams(a,r,s??void 0):"vectorField"===a.type?this._generateVectorFieldWebGLParams(a):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 p(e,this.lookup.colormapLut)}_symbolizeClassBreaks(e){const{canUseIndexedLUT:t}=this._analyzeClassBreaks(this.rendererJSON);if(this._isLUTChanged()){if(!this.bind().success)return e}return t?p(e,this.lookup.colormapLut):d(e,this.lookup.remapLut??[])}_symbolizeStretch(e,t){const{rasterInfo:r}=this,{pixelType:s,bandCount:a}=r,n=this.rendererJSON,i=["u8","u16","s8","s16"].includes(s);let l,u;const{dra:c}=n,{gamma:d}=this.lookup;if("histogramEqualization"===n.stretchType){const s=c?null:this.lookup?.histogramLut,o=b(n,{rasterInfo:r,pixelBlock:e,bandIds:t,returnHistogramLut:!s}),a=y(e,{...o,gamma:d,isRenderer:!0});u=h(a,{lut:c?o.histogramLut:s,offset:0})}else if(i){if(c){const o=b(n,{rasterInfo:r,pixelBlock:e,bandIds:t});l=g({pixelType:s,...o,gamma:d,rounding:"floor"})}else if(this._isLUTChanged()){if(!this.bind().success)return e;l=this.lookup?this.lookup.stretchLut:null}else l=this.lookup?this.lookup.stretchLut:null;if(!l)return e;a>1&&t?.length===o(e)?.pixels.length&&l?.lut.length===a&&(l={lut:t.map((e=>l.lut[e])),offset:l.offset}),u=h(e,l)}else{const s=b(n,{rasterInfo:r,pixelBlock:e,bandIds:t});u=y(e,{...s,gamma:d,isRenderer:!0})}if(n.colorRamp){if(this._isLUTChanged(!0)){if(!this.bind().success)return e}u=p(u,this.lookup?.colormapLut)}return u}_symbolizeShadedRelief(e,t){const r=this.rendererJSON,s={...r,...t},a=R(e,s);if(!r.colorRamp)return a;let n;if(this._isLUTChanged(!0)){if(!this.bind().success)return a;n=this.lookup?this.lookup.hsvMap:null}else n=this.lookup?this.lookup.hsvMap:null;if(!n)return a;const i=o(this.rasterInfo.statistics)?.[0]??{min:0,max:8e3};return x(a,e,n,i),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,o=e.field1;if(!o)return{success:!1,error:"Unsupported renderer; missing UniqueValueRenderer.field."};const n=e.defaultSymbol,i=1===t&&["u8","s8"].includes(s);if(!L(this.rasterInfo,o)&&!i)return{success:!1,error:"Unsupported data; UniqueValueRenderer is only supported on single band data with a valid raster attribute table."};const l=[];if(a(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[o]))),a=s?.symbol?.color;a?l.push([r.attributes[t.name]].concat(a)):n&&l.push([r.attributes[t.name]].concat(n.color))}))}else{if("value"!==o.toLowerCase())return{success:!1,error:'Unsupported renderer; UniqueValueRenderer.field must be "Value" when raster attribute table is not availalbe.'};e.uniqueValueInfos?.forEach((e=>{const t=e?.symbol?.color;t?l.push([parseInt(""+e.value,10)].concat(t)):n&&l.push([parseInt(""+e.value,10)].concat(n?.color))}))}if(0===l.length)return{success:!1,error:"Invalid UniqueValueRenderer. Cannot find matching records in the raster attribute table."};const u=m({colormap:l});return this.lookup={rendererJSON:e,colormapLut:u},this.canRenderInWebGL=!0,{success:!0}}_updateColormapRenderer(e){if(!V(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=m({colormap:t});return this.lookup={rendererJSON:e,colormapLut:r},this.canRenderInWebGL=!0,{success:!0}}_updateShadedReliefRenderer(e){if(!_(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 r=C(e.colorRamp,{interpolateAlpha:!0}),s=m({colormap:r}),o=[],a=s.indexedColormap;for(let e=0;e<a.length;e+=4){const r=t({r:a[e],g:a[e+1],b:a[e+2]});o.push([r.h/60,r.s/100,255*r.v/100])}this.lookup={rendererJSON:e,colormapLut:s,hsvMap:o}}else this.lookup=null;return this.canRenderInWebGL=!0,{success:!0}}_analyzeClassBreaks(e){const{attributeTable:t,pixelType:r}=this.rasterInfo,s=a(t)?t.fields.find((e=>"value"===e.name.toLowerCase())):null,o=a(t)?t.fields.find((t=>t.name.toLowerCase()===e.field.toLowerCase())):null,n=null!=s&&null!==o;return{canUseIndexedLUT:["u8","u16","s8","s16"].includes(r)||n,tableValueField:s,tableBreakField:o}}_updateClassBreaksRenderer(e){const{attributeTable:t}=this.rasterInfo,{canUseIndexedLUT:r,tableValueField:s,tableBreakField:o}=this._analyzeClassBreaks(e),n=e.classBreakInfos;if(!n?.length)return{success:!1,error:"Unsupported renderer; missing or invalid ClassBreaksRenderer.classBreakInfos."};const i=n.sort(((e,t)=>e.classMaxValue-t.classMaxValue)),l=i[i.length-1];let u=e.minValue;if(!r){const t=[];for(let e=0;e<i.length;e++)t.push({value:i[e].classMinValue??u,mappedColor:i[e].symbol.color}),u=i[e].classMaxValue;return t.push({value:l.classMaxValue,mappedColor:l.symbol.color}),this.lookup={rendererJSON:e,remapLut:t},this.canRenderInWebGL=!1,{success:!0}}const c=[];if(a(t)&&null!=s&&null!==o&&s!==o){const r=s.name,a=o.name,n=i[i.length-1],{classMaxValue:l}=n;u=e.minValue;for(const e of t.features){const t=e.attributes[r],s=e.attributes[a],o=s===l?n:s<u?null:i.find((({classMaxValue:e})=>e>s));o&&c.push([t].concat(o.symbol.color))}}else{u=Math.floor(e.minValue);for(let e=0;e<i.length;e++){const t=i[e];for(let e=u;e<t.classMaxValue;e++)c.push([e].concat(t.symbol.color));u=Math.ceil(t.classMaxValue)}l.classMaxValue===u&&c.push([l.classMaxValue].concat(l.symbol.color))}const p=m({colormap:c,fillUnspecified:!1});return this.lookup={rendererJSON:e,colormapLut:p},this.canRenderInWebGL=!0,{success:!0}}_isHistogramRequired(e){return"percentClip"===e||"histogramEqualization"===e}_isValidRasterStatistics(e){return a(e)&&e.length>0&&null!=e[0].min&&null!=e[0].max}_updateStretchRenderer(e){let{stretchType:t,dra:r}=e;if(!("none"===t||e.statistics?.length||this._isValidRasterStatistics(this.rasterInfo.statistics)||r))return{success:!1,error:"Unsupported renderer; StretchRenderer.statistics is required when dynamic range adjustment is not used."};const s=o(e.histograms||this.rasterInfo.histograms);!this._isHistogramRequired(e.stretchType)||s?.length||r||(t="minMax");const{computeGamma:a,useGamma:n,colorRamp:i}=e;let{gamma:l}=e;if(n&&a&&!l?.length){const t=e.statistics?.length?e.statistics:o(this.rasterInfo.statistics);l=S(this.rasterInfo.pixelType,t)}const u=this.rasterInfo.pixelType,c=!r&&["u8","u16","s8","s16"].includes(u);if("histogramEqualization"===t){const t=s.map((e=>k(e)));this.lookup={rendererJSON:e,histogramLut:t}}else if(c){const t=b(e,{rasterInfo:this.rasterInfo}),r=g({pixelType:u,...t,gamma:n?l:null,rounding:"floor"});this.lookup={rendererJSON:e,stretchLut:r}}if(i){const t=C(i,{interpolateAlpha:!0});this.lookup||(this.lookup={rendererJSON:e}),this.lookup.colormapLut=m({colormap:t}),this.lookup.rendererJSON=e}return this.lookup.gamma=n&&l?.length?l:null,this.canRenderInWebGL=!0,{success:!0}}_generateStretchWebGLParams(e,t,r){let s=null,o=null;const n=this.lookup&&this.lookup.colormapLut;t.colorRamp&&n&&(s=n.indexedColormap,o=n.offset),"histogramEqualization"===t.stretchType&&(t={...t,stretchType:"minMax"});const{gamma:i}=this.lookup,l=!!(t.useGamma&&i&&i.some((e=>1!==e))),{minCutOff:u,maxCutOff:c,outMin:p,outMax:d}=b(t,{rasterInfo:this.rasterInfo,pixelBlock:e,bandIds:r});let h=0;a(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=new Float32Array(f),g=s||l?1:255;let S;for(S=0;S<u.length;S++)y[S]=c[S]===u[S]?0:(d-p)/(c[S]-u[S])/g;const k=new Float32Array(f);if(l&&i)for(S=0;S<f;S++)i[S]>1?i[S]>2?k[S]=6.5+(i[S]-2)**2.5:k[S]=6.5+100*(2-i[S])**4:k[S]=1;return{bandCount:f,outMin:p/g,outMax:d/g,minCutOff:u,maxCutOff:c,factor:y,useGamma:l,gamma:l?i:[1,1,1],gammaCorrection:l?k:[1,1,1],colormap:s,colormapOffset:o,stretchType:t.stretchType,type:"stretch"}}_generateShadedReliefWebGLParams(e,t=!1,r={x:0,y:0}){let s=null,a=null;const n=this.lookup&&this.lookup.colormapLut;e.colorRamp&&n&&(s=n.indexedColormap,a=n.offset);const i={...e,isGCS:t,resolution:r},l=I(i),u=o(this.rasterInfo.statistics)?.[0];return{...l,minValue:u?.min??0,maxValue:u?.max??8e3,hillshadeType:"traditional"===e.hillshadeType?0:1,type:"hillshade",colormap:s,colormapOffset:a}}_generateVectorFieldWebGLParams(e){const{style:t,inputUnit:r,outputUnit:s,visualVariables:o,symbolTileSize:n,flowRepresentation:i}=e;let l;const u=this.rasterInfo.statistics?.[0].min??0,c=this.rasterInfo.statistics?.[0].max??50,p=o?.find((e=>"sizeInfo"===e.type))??{type:"sizeInfo",field:"Magnitude",maxDataValue:c,maxSize:.8*n,minDataValue:u,minSize:.2*n},d=p.minDataValue??u,h=p.maxDataValue??c,m=a(p.maxSize)&&a(p.minSize)?[p.minSize/n,p.maxSize/n]:[.2,.8];if("wind_speed"===t){const e=(m[0]+m[1])/2;m[0]=m[1]=e}const f=a(d)&&a(h)?[d,h]:null;if("classified_arrow"===t)if(a(d)&&a(h)&&a(p)){l=[];const e=(p.maxDataValue-p.minDataValue)/5;for(let t=0;t<6;t++)l.push(p.minDataValue+e*t)}else l=[0,1e-6,3.5,7,10.5,14];const y="flow_to"===i===("ocean_current_kn"===t||"ocean_current_m"===t)?0:Math.PI,b=o?.find((e=>"rotationInfo"===e.type));return{breakValues:l,dataRange:f,inputUnit:r,outputUnit:s,symbolTileSize:n,symbolPercentRange:m,style:t||"single_arrow",rotation:y,rotationType:this.rasterInfo.storageInfo?.tileInfo&&"vector-uv"===this.rasterInfo.dataType?"geographic":b?.rotationType||e.rotationType,type:"vectorField"}}};function O(e){return f(e)&&0!==e.validPixelCount}e([i({json:{write:!0}})],v.prototype,"rendererJSON",void 0),e([i({type:u,json:{write:!0}})],v.prototype,"rasterInfo",void 0),e([i({json:{write:!0}})],v.prototype,"lookup",void 0),e([i()],v.prototype,"canRenderInWebGL",void 0),v=e([l("esri.renderers.support.RasterSymbolizer")],v);const T=v;export{T as default};