UNPKG

@arcgis/core

Version:

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

3 lines (2 loc) • 16.9 kB
/* COPYRIGHT Esri - https://js.arcgis.com/5.0.8/LICENSE.txt */ import{__decorate as e}from"tslib";import t from"../../../../core/Accessor.js";import{forEach as s,result as i}from"../../../../core/asyncUtils.js";import"../../../../core/has.js";import a from"../../../../core/Logger.js";import{disposeMaybe as l,abortMaybe as r}from"../../../../core/maybe.js";import{throwIfAborted as o,isAbortError as n}from"../../../../core/promiseUtils.js";import c from"../../../../core/Queue.js";import{watch as h}from"../../../../core/reactiveUtils.js";import{property as b,subclass as u}from"../../../../core/accessorSupport/decorators.js";import{fromValues as p}from"../../../../core/libs/gl-matrix-2/factories/vec2f64.js";import{hydrateGraphic as d}from"../../../../layers/graphics/hydratedFeatures.js";import{createLabelFunction as y}from"../../../../layers/support/labelFormatUtils.js";import{hasCalloutSupport as g}from"../../../../symbols/callouts/calloutUtils.js";import{make as f}from"./Graphics3DCalloutSymbolLayerFactory.js";import{LineCalloutCreationContext as m,LineCalloutSymbolLayerRenderingInfo as C}from"./Graphics3DLineCalloutSymbolLayer.js";import{getGraphics3DSymbol as x}from"./graphicSymbolUtils.js";import{LabelInfo as _}from"./LabelInfo.js";import{LabelParameters as L}from"./LabelParameters.js";import{horizontalPlacementFromAnchor as v,verticalPlacementFromAnchor as G,textRenderAlignmentFromHorizontalPlacement as w}from"./placementUtils.js";import{placePointOnGeometry as A}from"./pointUtils.js";import{TextRenderer as D}from"../../webgl-engine/lib/TextRenderer.js";import{TextRenderParameters as T}from"../../webgl-engine/lib/TextRenderParameters.js";import{TextTextureAtlas as I}from"../../webgl-engine/lib/TextTextureAtlas.js";import{WebGLLayer as S}from"../../webgl-engine/lib/WebGLLayer.js";import{hasLayerBasedScaleVisibility as P,isInEffectiveScaleRange as R}from"../../../support/layerViewUtils.js";import{TaskPriority as V}from"../../../support/Scheduler.js";import{Yield as j}from"../../../support/Yield.js";class O{constructor(e,t){this.labelingContext=e,this.graphics3DGraphic=t,this.hasGraphics3DResources=!1,this.visible=!1,this.textureAtlasHandles=[],this.textInitialized=!1,this.textRenderers=new Array,this.textLabelPlacements=new Array}}class z{constructor(e,t,s,i,a){this.labelClass=e,this.graphics3DSymbol=t,this.graphics3DCalloutSymbolLayer=s,this.textRenderParameters=i,this.labelFunction=a,this.calloutSymbolLayerIndex=0,this.graphics=new Map,this.scaleVisibility=null}}class E{constructor(e,t,s,i,a,l,r,o){this.layer=t,this.graphics3DCore=s,this.scaleVisibility=i,this.emptySymbolLabelSupported=a,this.elevationInfoOverride=l,this.disablePlacement=r,this.active=o,this.labelClassAbortController=new AbortController,this._labelClassContexts=new Array,this.graphics=new Map,this.labelsToInitialize=new Map,this.stageLayer=new S(e,{pickable:!0},s.owner.layerViewUid)}destroy(){this.stageLayer.destroy()}get labelClassContexts(){return this._labelClassContexts}setLabelClassContext(e,t){this._labelClassContexts[e]=t}resetLabelClassContext(){this._labelClassContexts.length=0}}let F=class extends t{constructor(e){super(e),this._hudMaterials=new Map,this._calloutMaterials=new Map,this._dirty=!1,this._focusAreasLabelsQueue=new c,this._labels=new Map,this._labelingContexts=new Array}setup(){this.dispose(),this.addHandles([h(()=>this.view.state?.camera,()=>this.setDirty()),h(()=>this.view.state?.rasterPixelRatio,()=>this._resetAllLabels()),h(()=>this.view.focusAreasView?.polygons,()=>this._updateFocus()),this.view.resourceController.scheduler.registerTask(V.LABELER,this)]),P()&&this.addHandles(h(()=>this.view.scale,()=>this._updateScaleVisibility())),this._textTextureAtlas=new I({view:this.view})}dispose(){this.removeAllHandles(),this._textTextureAtlas=l(this._textTextureAtlas),this._hudMaterials.clear(),this._calloutMaterials.clear(),this._labelingContexts.length=0,this._labels.clear()}destroy(){this.dispose(),B.graphic=null,B.renderingInfo=null,B.layer=null}_updateFocus(){this._focusAreasLabelsQueue.clear(),this._labelingContexts.forEach(e=>{e.graphics.forEach(t=>{this._focusAreasLabelsQueue.push({graphic3DGraphic:t,labelingContext:e})})})}_activateLabelingContext(e){e.graphics.forEach((t,s)=>{const i=new O(e,t);this._labels.set(s,i),e.labelsToInitialize.set(s,i),t.setVisibilityFlag(16,1,!0)}),e.active=!0}_deactivateLabelingContext(e){e.graphics.forEach((e,t)=>{e.setVisibilityFlag(16,1,!1),this.setLabelGraphicVisibility(e,!1),e.clearLabelGraphics(),this._labels.delete(t)}),e.active=!1}_addLabelTextureToAtlas(e){if(this._textTextureAtlas)for(const t of e.graphics3DGraphic.labelLayers){if(!t.labelClass)continue;const s=e.textRenderers[t.labelClassContextIndex];s&&(e.textureAtlasHandles.push(this._textTextureAtlas.addText(s,e=>U(t.stageObject,e))),M(t.stageObject,s))}}_removeLabelTextureFromAtlas(e){e.textureAtlasHandles.forEach(e=>e.remove()),e.textureAtlasHandles.length=0}get readyToRun(){return this.view.ready&&(this._dirty||this.deconflictor.readyToRun||this._focusAreasLabelsQueue.length>0)}runTask(e){return this._updateLabels(e),this._applyFocusAreasUpdates(e),!this._dirty&&this.deconflictor.readyToRun&&this.deconflictor.runTask(e),j}_updateLabels(e){if(this._dirty){this._dirty=!1;for(const t of this._labelingContexts)if(t.active)if(H(t))this._dirty=!0;else if(Q(t.labelClassContexts)){if(null===t.labelClassContexts){this._deactivateLabelingContext(t);continue}this._createLabelClassContext(t),this._dirty=!0}else for(const[s,i]of t.labelsToInitialize)if(this._ensureGraphics3DResources(i)&&(this._labels.set(s,i),this.deconflictor.setDirty(),e.madeProgress()),(i.visible&&i.textInitialized||!i.visible&&i.hasGraphics3DResources)&&(t.labelsToInitialize.delete(s),e.madeProgress()),e.done){this._dirty=!0;break}this._dirty||this.notifyChange("updating")}}_applyFocusAreasUpdates(e){for(;this._focusAreasLabelsQueue.length>0&&!e.done;){e.madeProgress();const{graphic3DGraphic:t,labelingContext:s}=this._focusAreasLabelsQueue.pop();if(0===t.labelLayers.length||!s.active)continue;const i=A(t.graphic.geometry);if(null==i)continue;const a=this.view.focusAreasView?.containsGeometry(i)??!0;t.labelLayers.forEach(e=>{e.stageObject.geometries.some(e=>e.material.parameters.isFocused!==a)&&(this._removeGraphic(s,t),this._addGraphic(s,t),this.setDirty())})}0===this._focusAreasLabelsQueue.length&&(this.notifyChange("readyToRun"),this.notifyChange("updating"))}async _createLabelClassContextAsync(e){const t=e.labelClassAbortController?.signal;e.layer.when&&await e.layer.when(),o(t),e.scaleVisibility?.updateScaleRangeActive();const l=e.graphics3DCore,r=l.layer,n=r.labelingInfo?.filter(e=>!!e.symbol);if(!n||0===n.length)return;let c=!1;await s(n,async(s,r)=>{const n=s.symbol,h=x(l.getOrCreateGraphics3DSymbol(n));if(null==h)return void a.getLogger(this).error("Failed to create Graphics3DSymbol for label");await h.load(),o(t);let b=null;g(n)&&n.hasVisibleCallout()&&(b=f(n,l.symbolCreationContext),await b.load(),o(t));const u=await i(y(s,e.layer.fieldsIndex,this.view.spatialReference));if(o(t),!0===u.ok){const i=await this._createTextRenderParameters(h.symbol);o(t);const a=new z(s,h,b,i,u.value);this._updateLabelClassContextVisibility(a),e.setLabelClassContext(r,a)}else a.getLogger(this).error(`Label expression failed to evaluate: ${u.error}`),c=!0}),o(t)}async _createLabelClassContext(e){return null==e.labelClassPromise&&(e.labelClassPromise=this._createLabelClassContextAsync(e).catch(t=>{if(n(t))throw t;e.resetLabelClassContext()}).then(()=>{e.labelClassAbortController=null,this.notifyChange("updating")}).catch(()=>{}),this.notifyChange("updating")),e.labelClassPromise}async _createTextRenderParameters(e){const t=e.symbolLayers.at(0);return"text"!==t?.type?null:T.fromSymbol(t,this.view.state.rasterPixelRatio)}_destroyLabelClassContext(e){for(const s of e.labelClassContexts)s&&--s.graphics3DSymbol.referenced;const t=e.labelClassAbortController;e.labelClassAbortController=new AbortController,r(t),e.resetLabelClassContext(),e.labelClassPromise=null,this.notifyChange("updating")}_createTextSymbolGraphic(e,t,s,i,a,l){if(!this._textTextureAtlas)return null;const r=new L(s,v(s.anchor),G(s.anchor),e.text,p(e.displayWidth,e.displayHeight));return B.graphic=t,B.layer=i,B.renderingInfo=null,a.createLabel(B,r,this._hudMaterials,this._textTextureAtlas,()=>l.placement?.elevationOffset??null)}_createLineCalloutGraphic(e,t,s,i,a){B.graphic=e,B.layer=a;const l=i.screenOffset[0];return B.renderingInfo=new C(null,t,i.translation,i.centerOffset,l,i.centerOffsetUnits,i.elevationOffset),s.createGraphics3DGraphic(B,this._calloutMaterials)}_ensureGraphics3DResources(e){if(e.hasGraphics3DResources)return!1;const t=e.graphics3DGraphic;if(t.destroyed)return!1;this._ensureTextTextureResources(e);const s=e.labelingContext,i=s.labelClassContexts;if(Q(i)||!s.emptySymbolLabelSupported&&0===t.layers.length)return!1;let a=!1;const l=t.graphic,r=s.layer,o=W(s.layer);for(let n=0;n<i.length;n++){const c=e.textRenderers[n],h=e.textLabelPlacements[n],b=i[n];if(null==c||null==h||null==b)continue;const u=b.graphics3DSymbol,p=k(u),d=u.symbolLayers[0];if(!d)continue;d.setElevationInfoOverride(s.elevationInfoOverride);const y=new _(t,p,b.labelClass),g=this._createTextSymbolGraphic(c,l,h,r,d,y);if(null==g)return!1;g.labelClass=b.labelClass,g.labelClassContextIndex=n,t.addLabelGraphic(g,s.stageLayer),this.deconflictor.setPriority(t,b.textRenderParameters?.definition.size??0),t.setVisibilityFlag(16,1,o),t.setVisibilityFlag(16,2,b.scaleVisibility??!0),t.setVisibilityFlag(16,8,!1),P()&&b.graphics.set(l.uid,t),a=!0;const f=b.graphics3DCalloutSymbolLayer;if(f&&h.hasLabelVerticalOffset){f.setElevationInfoOverride(s.elevationInfoOverride);const e=this._createLineCalloutGraphic(l,p,f,h,r);null!=e&&(b.calloutSymbolLayerIndex=t.labelLayers.length,t.addLabelGraphic(e,s.stageLayer))}break}return a&&s.scaleVisibility?.updateGraphicLabelScaleVisibility(t),e.hasGraphics3DResources=!0,!0}_destroyGraphics3DResources(e){const t=e.labelingContext.labelClassContexts;for(const s of e.graphics3DGraphic.labelLayers){if(null==s.labelClass)continue;const e=t[s.labelClassContextIndex].graphics3DSymbol.symbolLayers[0];e?.onRemoveGraphic(s)}e.graphics3DGraphic.clearLabelGraphics(),e.hasGraphics3DResources=!1}_ensureTextTextureResources(e){if(e.textInitialized)return;const t=e.labelingContext,s=t.labelClassContexts;if(Q(s))return;const i=e.graphics3DGraphic.graphic;for(let l=0;l<s.length;l++){const r=s[l];if(e.textRenderers[l]=null,e.textLabelPlacements[l]=null,null==r?.textRenderParameters)continue;const o=r.labelFunction;let n;if("arcade"===o.type)try{const e=o.needsHydrationToEvaluate()?d(i,t.layer,null):i;n=o.evaluate(e)}catch(a){n=null}else n=o.evaluate(i);if(null==n||""===n||/^\s+$/.test(n))continue;const c=r.graphics3DSymbol;if(!c.symbolLayers[0])continue;const h=e.graphics3DGraphic,b="label-3d"===c.symbol?.type?c.symbol:null,u=r.labelClass,p=t.disablePlacement,y=new _(h,b,u,p).placement;if(null==y)continue;const g=v(y.anchor),f=w(g);e.textRenderers[l]=new D(n,f,r.textRenderParameters,I.maxSize),e.textLabelPlacements[l]=y}e.textInitialized=!0}_destroyTextTextureResources(e){e.textInitialized=!1,e.textRenderers.length=0,e.textLabelPlacements.length=0}_addGraphic(e,t){const s=t.graphic.uid;if(e.graphics.set(s,t),e.active){const i=new O(e,t);this._labels.set(s,i),e.labelsToInitialize.set(s,i)}this.setDirty(),this.deconflictor.setDirty()}_updateGraphicGeometry(e,t){const s=t.graphic.uid,i=this._labels.get(s);if(!i)return!0;for(const a of i.graphics3DGraphic.labelLayers){if(null==a.labelClass)continue;if(!e.labelClassContexts[a.labelClassContextIndex].graphics3DSymbol.symbolLayers[0].updateGeometry(t.graphic,a))return!1}return this.setDirty(),this.deconflictor.setDirty(),!0}_removeGraphic(e,t){const s=t.graphic.uid,i=this._labels.get(s);e.graphics.delete(s),e.labelClassContexts.forEach(e=>e?.graphics.delete(s)),i&&(this._destroyGraphic(i,s),e.labelsToInitialize.delete(s),this.setDirty(),this.deconflictor.setDirty())}_destroyGraphic(e,t){this._labels.delete(t),e.textureAtlasHandles.length&&this._removeLabelTextureFromAtlas(e),this._destroyTextTextureResources(e),e.hasGraphics3DResources&&this._destroyGraphics3DResources(e)}async _labelingInfoChange(e,t){if(!t)return this._visibilityInfoChange(e),this._resetLabels(e),this._createLabelClassContext(e);for(const s of t){const t=e.graphics.get(s);t&&(this._removeGraphic(e,t),this._addGraphic(e,t))}}_globalPropertyChanged(e,t){for(const s of t.labelClassContexts){if(!s)continue;const i=new Map;t.graphics.forEach(e=>i.set(e.graphic.uid,e));const a=e=>e.labelLayers[0];if(s.graphics3DSymbol.symbolLayers[0].globalPropertyChanged(e,i,a),s.graphics3DCalloutSymbolLayer){const t=e=>e.labelLayers[s.calloutSymbolLayerIndex];s.graphics3DCalloutSymbolLayer.globalPropertyChanged(e,i,t)}}}_visibilityInfoChange(e){const t=W(e.layer);t&&!e.active&&this._activateLabelingContext(e),!t&&e.active&&this._deactivateLabelingContext(e),this.setDirty()}_resetAllLabels(){for(const e of this._labelingContexts)this._resetLabels(e)}_resetLabels(e){e.graphics.forEach((t,s)=>{const i=this._labels.get(s);i&&(this._destroyGraphic(i,s),i.visible=!1,e.labelsToInitialize.set(s,i))}),this._destroyLabelClassContext(e),this.setDirty(),this.deconflictor.setDirty()}_findLabelingContext(e){for(const t of this._labelingContexts)if(t.graphics3DCore===e)return t;return null}addGraphicsOwner(e,t,s){const i=s?.emptySymbolLabelSupported||!1,a=s?.elevationInfoOverride||null,l=s?.disablePlacement||null;if(this._findLabelingContext(e))return;const r=e.layer,o=new E(this.view.stage,r,e,t,i,a,l,W(r));return this._labelingContexts.push(o),this.setDirty(),{addGraphic:e=>this._addGraphic(o,e),removeGraphic:e=>this._removeGraphic(o,e),updateGraphicGeometry:e=>this._updateGraphicGeometry(o,e),layerLabelsEnabled:()=>W(o.layer),labelingInfoChange:e=>this._labelingInfoChange(o,e),elevationInfoChange:()=>this._globalPropertyChanged("elevationInfo",o),screenSizePerspectiveEnabledChanged:()=>this._globalPropertyChanged("screenSizePerspectiveEnabled",o),slicePlaneEnabledChange:()=>this._globalPropertyChanged("slicePlaneEnabled",o),visibilityInfoChange:()=>this._visibilityInfoChange(o),reset:()=>this._resetLabels(o),remove:()=>this._removeGraphicsOwner(e),setDirty:()=>this.setDirty()}}_removeGraphicsOwner(e){const t=this._findLabelingContext(e);if(!t)return;const s=this._labelingContexts.indexOf(t);this._labelingContexts.splice(s,1),t.graphics.forEach(e=>this._removeGraphic(t,e)),t.destroy(),this.setDirty()}_updateScaleVisibility(){for(const e of this._labelingContexts)if(e.active&&!H(e))for(const t of e.labelClassContexts)this._updateLabelClassContextVisibility(t)}_updateLabelClassContextVisibility(e){if(!e||!P())return;const{labelClass:t,graphics:s}=e,i={minScale:t.minScale,maxScale:t.maxScale},a=R(i,this.view.scale),l=null==e.scaleVisibility||e.scaleVisibility!==a;e.scaleVisibility=a,l&&s.size&&(s.forEach(e=>e.setVisibilityFlag(16,2,a)),this.deconflictor.setDirty(),this.setDirty())}setLabelGraphicVisibility(e,t){const s=e.graphic.uid,i=this._labels.get(s);i&&i.visible!==t&&(t&&!i.textureAtlasHandles.length?(this._addLabelTextureToAtlas(i),i.textInitialized||i.labelingContext.labelsToInitialize.set(s,i)):!t&&i.textureAtlasHandles.length&&this._removeLabelTextureFromAtlas(i),i.visible=t,this.setDirty())}setDirty(){!this._dirty&&this._labelingContexts.length>0&&(this._dirty=!0,this.notifyChange("updating"))}get updating(){return this._dirty||this._textTextureAtlas?.updating||this.deconflictor.updating||this._labelingContexts.some(e=>H(e))||this._focusAreasLabelsQueue.length>0}get updatingProgress(){if(!this.updating||!this._textTextureAtlas)return 1;const e=this._labelingContexts.length>0?this._labelingContexts.reduce((e,t)=>e+(H(t)?0:1),0)/this._labelingContexts.length:1;return(this._dirty?0:.3)+(this._textTextureAtlas.updating?0:.1)+.1*e+.5*this.deconflictor.updatingProgress}get usedMemory(){return this._textTextureAtlas?.usedMemory??0}get test(){}};function M(e,t){e.geometries[0].setAttributeData("size",[t.displayWidth,t.displayHeight]),e.geometryVertexAttributeUpdated(e.geometries[0],"size")}function U(e,t){e.geometries[0].setAttributeData("uvi",t),e.geometryVertexAttributeUpdated(e.geometries[0],"uvi",!0)}function H(e){return!!e.labelClassPromise&&!!e.labelClassAbortController}function Q(e){return 0===(e?.length??0)}function k(e){return"label-3d"===e.symbol?.type?e.symbol:null}function W(e){return!!e.labelsVisible&&!!e.labelingInfo?.some(e=>!!e.symbol)}e([b({constructOnly:!0})],F.prototype,"view",void 0),e([b({constructOnly:!0})],F.prototype,"deconflictor",void 0),e([b()],F.prototype,"_textTextureAtlas",void 0),e([b({type:Boolean,readOnly:!0})],F.prototype,"updating",null),F=e([u("esri.views.3d.layers.graphics.Labeler")],F);const B=new m(null,null,null);export{F as Labeler,W as areLabelsVisible};