UNPKG

@arcgis/core

Version:

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

6 lines (5 loc) • 13.4 kB
/* 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"../../../Graphic.js";import{pickRandom as r}from"../../../core/arrayUtils.js";import a from"../../../core/Error.js";import{timeout as s,throwIfAborted as i}from"../../../core/promiseUtils.js";import{whenOnce as o}from"../../../core/reactiveUtils.js";import{property as n}from"../../../core/accessorSupport/decorators/property.js";import"../../../core/has.js";import"../../../core/Logger.js";import{subclass as l}from"../../../core/accessorSupport/decorators/subclass.js";import{kebabDict as u}from"../../../layers/support/fieldType.js";import{isNumericField as p}from"../../../layers/support/fieldUtils.js";import m from"../../../rest/support/FeatureSet.js";import{summaryStatistics as c,uniqueValues as d,classBreaks as h,histogram as y}from"../../statistics/support/statsWorker.js";import{WorkerClient as f}from"../../statistics/support/WorkerClient.js";import{getFieldsList as g,isAnyDateField as w,fieldDelimiter as F}from"../utils.js";import _ from"./FeatureLayerAdapter.js";import S from"./LayerAdapter.js";import{getMissingFields as v,ensureFeaturesJSON as x,getViewInfoParams as L,getUniqueValuesFromFeatureSet as E,getHistogramFromFeatureSet as C,getDomainsForFields as T}from"./support/utils.js";import{createUVResult as z}from"../../../statistics/utils.js";let A=class extends S{constructor(e){super(e),this._featureLayerAdapter=null,this.workerClient=null,this.adapterName="scene-layer-adapter"}destroy(){this.workerClient?.destroy()}_hasCachedStatistics(e){return this.layer.hasCachedStatistics(e)}_updateQuery(e,t=[],r=[]){if(!e||!r.length)return e;const a=this.layer.objectIdField,s=e.clone(),i=t.filter((e=>{const t=this.layer.getField(e);return!r.includes(t.name)})),o=i.some((e=>this.layer.getField(e).name===a));return s.outFields=o?i:[...i,a],s}async _fetchFeaturesFromMemory(e,t,r){if(!e)throw new a("scene-layer-adapter:insufficient-data","view is required to fetch the features from layerView");const n=await e.whenLayerView(this.layer),l=new AbortController,u=l.signal,p=o((()=>!n.updating),u);await s(p,5e3,l);const m=v(this,r,n);i(u);const c=this._updateQuery(t,r??[],m),d=await n.queryFeatures(c,{signal:u});i(u);const h=d.features;return m.length?n.whenGraphicAttributes(h,m):h}async _fetchFeaturesJSONFromMemory(e,t,r){return this._fetchFeaturesFromMemory(e,t,r).then(x)}_fetchFeaturesForStats(e,t){return g({field:e.field,normalizationField:e.normalizationField,valueExpression:e.valueExpression}).then((r=>this.getSampleFeatures({sampleSize:-1,view:e.view,returnGeometry:e.returnGeometry,requiredFields:r,signal:e.signal},t)))}async _processStatsFromMemoryParams(e){const t=e.features;if(t?.length){return t.length&&"declaredClass"in t[0]&&"esri.Graphic"===t[0].declaredClass?{graphics:t}:{featuresJSON:t}}const{view:r,field:s,normalizationField:i,valueExpression:o,signal:n}=e,l=await this._fetchFeaturesForStats({field:s,valueExpression:o,normalizationField:i,view:r,signal:n},null);if(!l?.length)throw new a("scene-layer-adapter:insufficient-data","No features are available to calculate statistics");return{graphics:l}}_getCachedStatistics(e,t){const r=this.layer;return e.valueExpression||e.sqlExpression||e.sqlWhere||e.minValue||e.maxValue?Promise.reject(new a("scene-layer-adapter:not-supported","This Layer does not support calculating statistics when 'valueExpression', 'sqlExpression', 'sqlWhere', 'minValue' or 'maxValue' is specified")):r.queryCachedStatistics(t?.name,{signal:e.signal}).then((e=>{const t=e.stats,{min:r,max:a,totalValuesCount:s}=t;let{avg:i,stddev:o,sum:n,variance:l,count:u}=t;return 0===r&&0===a||(i=0===i?null:i,n=0===n?null:n,o=0===o?null:o,l=0===l?null:l,u=0===u?null:u),null==u&&(null!=n&&null!=i?u=Math.round(n/i):null!=s&&(u=s)),{avg:i,count:u,max:a,min:r,stddev:o,sum:n,variance:l}}))}async _getNormalizationTotal(e,t,r){const s={include:["sum"]},i=(t?await this.workerClient.summaryStatistics({field:e,outStatisticTypes:s},t):await c({attribute:{field:e,outStatisticTypes:s},features:r})).sum;if(null==i)throw new a("scene-layer-adapter:invalid","invalid normalizationTotal");return i}async _getSummaryStatisticsFromMemory(e,t){const{view:r,field:a,normalizationField:s,valueExpression:i}=e,{featuresJSON:o,graphics:n}=await this._processStatsFromMemoryParams(e),l={field:a,valueExpression:i,normalizationType:e.normalizationType,normalizationField:s,normalizationTotal:e.normalizationTotal,minValue:e.minValue,maxValue:e.maxValue,outStatisticTypes:e.outStatisticTypes};return e.valueExpression&&r&&o&&(l.fieldType=t?.type?u.toJSON(t.type):null,l.viewInfoParams=L(r),l.timeZone=r.timeZone),"percent-of-total"===e.normalizationType&&null==e.normalizationTotal&&(l.normalizationTotal=await this._getNormalizationTotal(a,o,n)),o?this.workerClient.summaryStatistics(l,o):c({attribute:l,features:n})}_getCachedStatisticsForUniqueValues(e,r){const s=this.layer,i=r?.name,o=r&&e.field?this.getFieldDomain(e.field):null;return e.valueExpression||e.sqlExpression||e.sqlWhere?Promise.reject(new a("scene-layer-adapter:not-supported","This Layer does not support calculating statistics when 'valueExpression', 'sqlExpression' or 'sqlWhere' is specified")):s.queryCachedStatistics(i,{signal:e.signal}).then((a=>{const o=a.stats;if(!o.mostFrequentValues)throw new Error;const n=a.labels?.labels,l={},u=[],c="countOF"+i;o.mostFrequentValues.forEach((e=>{const a=new t({attributes:{}});a.attributes[i]=r&&r.name!==s.objectIdField&&(p(r)||w(r))?Number(e.value):e.value,a.attributes[c]=e.count,u.push(a)})),n&&n.forEach((e=>{l[e.value]=e.label}));const d=new m({features:u});return E(d,{layer:this,field:e.field,labels:l,view:e.view,signal:e.signal})})).then((t=>z(t,[o],e.returnAllCodedValues)))}async _getUniqueValuesFromMemory(e,t){const{view:r,field:a,field2:s,field3:i,valueExpression:o,returnAllCodedValues:n}=e,l={field:a,field2:s,field3:i,fieldDelimiter:F,valueExpression:o,domains:t,returnAllCodedValues:n},{featuresJSON:u,graphics:p}=await this._processStatsFromMemoryParams(e);return e.valueExpression&&r&&u&&(l.viewInfoParams=L(r),l.timeZone=r.timeZone),u?this.workerClient.uniqueValues(l,u):d({attribute:l,features:p})}_getCachedStatisticsForHistogram(e,t){const r=this.layer;return e.valueExpression||e.sqlExpression||e.sqlWhere||e.normalizationType?Promise.reject(new a("scene-layer-adapter:not-supported","This Layer does not support calculating statistics when 'valueExpression' or 'sqlExpression' or 'sqlWhere' or 'normalizationType' is specified")):r.queryCachedStatistics(t&&t.name,{signal:e.signal}).then((t=>{const r=t.stats,{minValue:a,maxValue:s}=e,i=null!=a?a:r.min,o=null!=s?s:r.max,n=e.numBins||10,l=j(r.histogram,i,o,n);return C(l,i,o,n)}))}async _getClassBreaksFromMemory(e){const{view:t,field:r,normalizationField:a,valueExpression:s}=e,{featuresJSON:i,graphics:o}=await this._processStatsFromMemoryParams(e),n={field:r,valueExpression:s,normalizationType:e.normalizationType,normalizationField:a,normalizationTotal:e.normalizationTotal,minValue:e.minValue,maxValue:e.maxValue,standardDeviationInterval:e.standardDeviationInterval,classificationMethod:e.classificationMethod,numClasses:e.numClasses};return e.valueExpression&&t&&i&&(n.viewInfoParams=L(t),n.timeZone=t.timeZone),"percent-of-total"===e.normalizationType&&null==e.normalizationTotal&&(n.normalizationTotal=await this._getNormalizationTotal(r,i,o)),i?this.workerClient.classBreaks(n,i):h({attribute:n,features:o})}async _getHistogramFromMemory(e){const{view:t,field:r}=e,{featuresJSON:a,graphics:s}=await this._processStatsFromMemoryParams(e),i={field:r,valueExpression:e.valueExpression,normalizationType:e.normalizationType,normalizationField:e.normalizationField,normalizationTotal:e.normalizationTotal,minValue:e.minValue,maxValue:e.maxValue,standardDeviationInterval:e.standardDeviationInterval,classificationMethod:e.classificationMethod,numBins:e.numBins};return e.valueExpression&&t&&a&&(i.viewInfoParams=L(t),i.timeZone=t.timeZone),"percent-of-total"===e.normalizationType&&null==e.normalizationTotal&&(i.normalizationTotal=await this._getNormalizationTotal(r,a,s)),a?this.workerClient.histogram(i,a):y({attribute:i,features:s})}getField(e){return this.layer.getField(e??"")}getFieldUsageInfo(e){const t=this.getField(e);if(!t)return null;const r=this.layer.getFieldUsageInfo(t.name);return{supportsLabelingInfo:r.supportsLabelingInfo,supportsPopupTemplate:r.supportsPopupTemplate,supportsRenderer:r.supportsRenderer,supportsLayerQuery:r.supportsLayerQuery,supportsStatistics:!0}}getFieldDomain(e,t){return this._featureLayerAdapter?this._featureLayerAdapter.getFieldDomain(e,t):null}createQuery(){return this.layer.createQuery()}summaryStatistics(e){const t=this.getField(e.field);if(this._featureLayerAdapter)return this._featureLayerAdapter.summaryStatistics(e);if(e.filter)throw new a("scene-layer-adapter:not-supported","filter is not supported");return this._hasCachedStatistics(t?.name)?this._getCachedStatistics(e,t).catch((()=>(i(e.signal),this._getSummaryStatisticsFromMemory(e,t)))):this._getSummaryStatisticsFromMemory(e,t)}async uniqueValues(e){if(this._featureLayerAdapter)return this._featureLayerAdapter.uniqueValues(e);if(e.filter)throw new a("scene-layer-adapter:not-supported","filter is not supported");const t=await T(e,this),{field:r,field2:s}=e,o=r&&s,n=this.getField(r);return!o&&n&&this._hasCachedStatistics(n.name)?this._getCachedStatisticsForUniqueValues(e,n).catch((()=>(i(e.signal),this._getUniqueValuesFromMemory(e,t)))):this._getUniqueValuesFromMemory(e,t)}histogram(e){const t=this.getField(e.field);if(this._featureLayerAdapter)return this._featureLayerAdapter.histogram(e);if(e.filter)throw new a("scene-layer-adapter:not-supported","filter is not supported");return t&&this._hasCachedStatistics(t.name)?this._getCachedStatisticsForHistogram(e,t).catch((()=>(i(e.signal),this._getHistogramFromMemory(e)))):this._getHistogramFromMemory(e)}classBreaks(e){const t=this.getField(e.field);if(this._featureLayerAdapter)return this._featureLayerAdapter.classBreaks(e);if(e.filter)throw new a("scene-layer-adapter:not-supported","filter is not supported");return this._hasCachedStatistics(t?.name)?Promise.reject(new a("scene-layer-adapter:not-supported","Cached stats not supported")):this._getClassBreaksFromMemory(e)}queryFeatureCount(e){return this._featureLayerAdapter?this._featureLayerAdapter.queryFeatureCount(e):Promise.reject(new a("scene-layer-adapter:not-supported","SceneLayer without associated FeatureLayer does not support count query"))}generateRenderer(e,t){return this._featureLayerAdapter?this._featureLayerAdapter.generateRenderer(e,t):Promise.reject(new a("scene-layer-adapter:not-supported","SceneLayer without associated FeatureLayer does not support generateRenderer operation"))}heatmapStatistics(e){return this._featureLayerAdapter?this._featureLayerAdapter.heatmapStatistics(e):Promise.reject(new a("scene-layer-adapter:not-supported","SceneLayer without associated FeatureLayer does not support heatmapStatistics operation"))}async predominantCategories(e){if(this._featureLayerAdapter)return this._featureLayerAdapter.predominantCategories(e);throw new a("scene-layer-adapter:not-supported","SceneLayer without associated FeatureLayer does not support predominantCategories")}async getSampleFeatures(e,t){if(e.filter)throw new a("scene-layer-adapter:not-supported","filter is not supported");const{view:s,sampleSize:o,requiredFields:n,returnGeometry:l,signal:u}=e,p=1,m="json"===t,c=this.createQuery();c.outFields=n,c.returnGeometry=!!l,c.where=null,c.num=o;let d=[];try{if(d=m?await this._fetchFeaturesJSONFromMemory(s,c,n):await this._fetchFeaturesFromMemory(s,c,n),d.length&&null!=o&&o>0&&o<=d.length)return r(d,o,p)}catch(y){i(u)}let h=null;if(this._featureLayerAdapter){const r={...e};delete r.view,h=await this._featureLayerAdapter.getSampleFeatures(r,t)}return h?.length?h:r(d,d.length,p)}load(e){const t=this.layer.load(e).then((async t=>{this.workerClient=f.getInstance(),await this.workerClient.open(e.signal);const r=t.associatedLayer;if(this.geometryType=t.geometryType,null!=r){this._featureLayerAdapter=new _({layer:r});return this._featureLayerAdapter.load(e).then((()=>{this.objectIdField=this._featureLayerAdapter.objectIdField,this.supportsSQLExpression=this._featureLayerAdapter.supportsSQLExpression,this.minScale=this._featureLayerAdapter.minScale,this.maxScale=this._featureLayerAdapter.maxScale,this.fullExtent=this._featureLayerAdapter.fullExtent}))}this.objectIdField=t.objectIdField,this.supportsSQLExpression=!1,this.hasQueryEngine=!1,this.fullExtent=t.fullExtent}));return this.addResolvingPromise(t),Promise.resolve(this)}};function j(e,r=e.minimum,a=e.maximum,s){const i=[];for(let t=0;t<s;t++)i[t]=0;const o=e.counts.length,n=e.minimum,l=e.maximum;for(let t=0;t<o;t++){const u=(t+.5)/o,p=((1-u)*n+u*l-r)/(a-r)*s;p>=0&&p<=s&&(i[p===s?s-1:Math.floor(p)]+=e.counts[t])}const u=[];return i.forEach(((e,r)=>{const a=new t({attributes:{}});a.attributes.EXPR_1=r+1,a.attributes.countOFExpr=e,u.push(a)})),new m({features:u})}e([n({readOnly:!0})],A.prototype,"adapterName",void 0),e([n({constructOnly:!0})],A.prototype,"layer",void 0),A=e([l("esri.smartMapping.support.adapters.SceneLayerAdapter")],A);export{A as default};