UNPKG

@arcgis/core

Version:

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

3 lines (2 loc) 13.1 kB
/* COPYRIGHT Esri - https://js.arcgis.com/5.0.8/LICENSE.txt */ import{__decorate as e}from"tslib";import t from"../../../Graphic.js";import{pickRandom as a}from"../../../core/arrayUtils.js";import r 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,subclass as l}from"../../../core/accessorSupport/decorators.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=[],a=[]){if(!e||!a.length)return e;const r=this.layer.objectIdField,s=e.clone(),i=t.filter(e=>{const t=this.layer.getField(e);return!a.includes(t.name)}),o=i.some(e=>this.layer.getField(e).name===r);return s.outFields=o?i:[...i,r],s}async _fetchFeaturesFromMemory(e,t,a){if(!e)throw new r("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,a,n);i(u);const c=this._updateQuery(t,a??[],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,a){return this._fetchFeaturesFromMemory(e,t,a).then(x)}_fetchFeaturesForStats(e,t){return g({field:e.field,normalizationField:e.normalizationField,valueExpression:e.valueExpression}).then(a=>this.getSampleFeatures({sampleSize:-1,view:e.view,returnGeometry:e.returnGeometry,requiredFields:a,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:a,field:s,normalizationField:i,valueExpression:o,signal:n}=e,l=await this._fetchFeaturesForStats({field:s,valueExpression:o,normalizationField:i,view:a,signal:n},null);if(!l?.length)throw new r("scene-layer-adapter:insufficient-data","No features are available to calculate statistics");return{graphics:l}}_getCachedStatistics(e,t){const a=this.layer;return e.valueExpression||e.sqlExpression||e.sqlWhere||e.minValue||e.maxValue?Promise.reject(new r("scene-layer-adapter:not-supported","This Layer does not support calculating statistics when 'valueExpression', 'sqlExpression', 'sqlWhere', 'minValue' or 'maxValue' is specified")):a.queryCachedStatistics(t?.name,{signal:e.signal}).then(e=>{const t=e.stats,{min:a,max:r,totalValuesCount:s}=t;let{avg:i,stddev:o,sum:n,variance:l,count:u}=t;return 0===a&&0===r||(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:r,min:a,stddev:o,sum:n,variance:l}})}async _getNormalizationTotal(e,t,a){const s={include:["sum"]},i=(t?await this.workerClient.summaryStatistics({field:e,outStatisticTypes:s},t):await c({attribute:{field:e,outStatisticTypes:s},features:a})).sum;if(null==i)throw new r("scene-layer-adapter:invalid","invalid normalizationTotal");return i}async _getSummaryStatisticsFromMemory(e,t){const{view:a,field:r,normalizationField:s,valueExpression:i}=e,{featuresJSON:o,graphics:n}=await this._processStatsFromMemoryParams(e),l={field:r,valueExpression:i,normalizationType:e.normalizationType,normalizationField:s,normalizationTotal:e.normalizationTotal,minValue:e.minValue,maxValue:e.maxValue,outStatisticTypes:e.outStatisticTypes};return e.valueExpression&&a&&o&&(l.fieldType=t?.type?u.toJSON(t.type):null,l.viewInfoParams=L(a),l.timeZone=a.timeZone),"percent-of-total"===e.normalizationType&&null==e.normalizationTotal&&(l.normalizationTotal=await this._getNormalizationTotal(r,o,n)),o?this.workerClient.summaryStatistics(l,o):c({attribute:l,features:n})}_getCachedStatisticsForUniqueValues(e,a){const s=this.layer,i=a?.name,o=a&&e.field?this.getFieldDomain(e.field):null;return e.valueExpression||e.sqlExpression||e.sqlWhere?Promise.reject(new r("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(r=>{const o=r.stats;if(!o.mostFrequentValues)throw new Error;const n=r.labels?.labels,l={},u=[],c="countOF"+i;o.mostFrequentValues.forEach(e=>{const r=new t({attributes:{}});r.attributes[i]=a&&a.name!==s.objectIdField&&(p(a)||w(a))?Number(e.value):e.value,r.attributes[c]=e.count,u.push(r)}),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:a,field:r,field2:s,field3:i,valueExpression:o,returnAllCodedValues:n}=e,l={field:r,field2:s,field3:i,fieldDelimiter:F,valueExpression:o,domains:t,returnAllCodedValues:n},{featuresJSON:u,graphics:p}=await this._processStatsFromMemoryParams(e);return e.valueExpression&&a&&u&&(l.viewInfoParams=L(a),l.timeZone=a.timeZone),u?this.workerClient.uniqueValues(l,u):d({attribute:l,features:p})}_getCachedStatisticsForHistogram(e,t){const a=this.layer;return e.valueExpression||e.sqlExpression||e.sqlWhere||e.normalizationType?Promise.reject(new r("scene-layer-adapter:not-supported","This Layer does not support calculating statistics when 'valueExpression' or 'sqlExpression' or 'sqlWhere' or 'normalizationType' is specified")):a.queryCachedStatistics(t&&t.name,{signal:e.signal}).then(t=>{const a=t.stats,{minValue:r,maxValue:s}=e,i=null!=r?r:a.min,o=null!=s?s:a.max,n=e.numBins||10,l=V(a.histogram,i,o,n);return C(l,i,o,n)})}async _getClassBreaksFromMemory(e){const{view:t,field:a,normalizationField:r,valueExpression:s}=e,{featuresJSON:i,graphics:o}=await this._processStatsFromMemoryParams(e),n={field:a,valueExpression:s,normalizationType:e.normalizationType,normalizationField:r,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(a,i,o)),i?this.workerClient.classBreaks(n,i):h({attribute:n,features:o})}async _getHistogramFromMemory(e){const{view:t,field:a}=e,{featuresJSON:r,graphics:s}=await this._processStatsFromMemoryParams(e),i={field:a,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&&r&&(i.viewInfoParams=L(t),i.timeZone=t.timeZone),"percent-of-total"===e.normalizationType&&null==e.normalizationTotal&&(i.normalizationTotal=await this._getNormalizationTotal(a,r,s)),r?this.workerClient.histogram(i,r):y({attribute:i,features:s})}getField(e){return this.layer.getField(e??"")}getFieldUsageInfo(e){const t=this.getField(e);if(!t)return null;const a=this.layer.getFieldUsageInfo(t.name);return{supportsLabelingInfo:a.supportsLabelingInfo,supportsPopupTemplate:a.supportsPopupTemplate,supportsRenderer:a.supportsRenderer,supportsLayerQuery:a.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 r("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 r("scene-layer-adapter:not-supported","filter is not supported");const t=await T(e,this),{field:a,field2:s}=e,o=a&&s,n=this.getField(a);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 r("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 r("scene-layer-adapter:not-supported","filter is not supported");return this._hasCachedStatistics(t?.name)?Promise.reject(new r("scene-layer-adapter:not-supported","Cached stats not supported")):this._getClassBreaksFromMemory(e)}queryFeatureCount(e){return this._featureLayerAdapter?this._featureLayerAdapter.queryFeatureCount(e):Promise.reject(new r("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 r("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 r("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 r("scene-layer-adapter:not-supported","SceneLayer without associated FeatureLayer does not support predominantCategories")}async getSampleFeatures(e,t){if(e.filter)throw new r("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 a(d,o,p)}catch(y){i(u)}let h=null;if(this._featureLayerAdapter){const a={...e};delete a.view,h=await this._featureLayerAdapter.getSampleFeatures(a,t)}return h?.length?h:a(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 a=t.associatedLayer;if(this.geometryType=t.geometryType,null!=a){this._featureLayerAdapter=new _({layer:a});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 V(e,a=e.minimum,r=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-a)/(r-a)*s;p>=0&&p<=s&&(i[p===s?s-1:Math.floor(p)]+=e.counts[t])}const u=[];return i.forEach((e,a)=>{const r=new t({attributes:{}});r.attributes.EXPR_1=a+1,r.attributes.countOFExpr=e,u.push(r)}),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};