@arcgis/core
Version:
ArcGIS Maps SDK for JavaScript: A complete 2D and 3D mapping and data visualization API
6 lines (5 loc) • 4.5 kB
JavaScript
/*
All material copyright ESRI, All Rights Reserved, unless otherwise specified.
See https://js.arcgis.com/4.32/esri/copyright.txt for details.
*/
import{LRUCache as e}from"../../../../core/LRUCache.js";import{fromValues as i,create as t,intersects as l}from"../../../../geometry/support/aaBoundingRect.js";import s from"../../tiling/TileCoverage.js";import o from"../../tiling/TileKey.js";const r=512,n=1e-6,a=(e,i)=>e+1/(1<<2*i);class h{constructor(i,t){this._tiles=new Map,this._tileCache=new e(40,(e=>e.dispose())),this._viewSize=[0,0],this._visibleTiles=new Map,this.acquireTile=i.acquireTile,this.releaseTile=i.releaseTile,this.tileInfoView=i.tileInfoView,this._container=t}destroy(){for(const e of this._tiles.values())e.dispose();this._tiles=null,this._tileCache.clear(),this._tileCache=null}update(e){this._updateCacheSize(e);const i=this.tileInfoView,t=i.getTileCoverage(e.state,0,!0,"smallest");if(!t)return!0;const{spans:l,lodInfo:r}=t,{level:n}=r,a=this._tiles,h=new Set,c=new Set;for(const{row:s,colFrom:_,colTo:f}of l)for(let e=_;e<=f;e++){const i=o.getId(n,s,r.normalizeCol(e),r.getWorldForColumn(e)),t=this._getOrAcquireTile(i);h.add(i),t.processed()?this._addToContainer(t):c.add(new o(i))}for(const[s,o]of a)o.isCoverage=h.has(s);for(const s of c)this._findPlaceholdersForMissingTiles(s,h);let d=!1;for(const[s,o]of a)o.neededForCoverage=h.has(s),o.neededForCoverage||o.isHoldingForFade&&i.intersects(t,o.key)&&h.add(s),o.isFading&&(d=!0);for(const s of this._tiles.keys())h.has(s)||this._releaseTile(s);return s.pool.release(t),!d}clear(){this._tiles.clear(),this._tileCache.clear(),this._visibleTiles.clear()}clearCache(){this._tileCache.clear()}getIntersectingTiles(e,s,o,r,n){const a=[0,0],h=[0,0];r.toMap(a,e-o,s+o),r.toMap(h,e+o,s-o);const c=Math.min(a[0],h[0]),d=Math.min(a[1],h[1]),_=Math.max(a[0],h[0]),f=Math.max(a[1],h[1]),T=i(c,d,_,f),u=t(),p=[];for(const i of this._visibleTiles.values())this.tileInfoView.getTileBounds(u,i.key),l(T,u)&&p.push(i);if(null!=n&&n.length>0){const e=new Set(p.map((e=>e.id))),i=n.filter((i=>!e.has(i.tileKey.id))).map((e=>this._visibleTiles.get(e.tileKey.id))).filter((e=>void 0!==e));p.push(...i)}return p}_findPlaceholdersForMissingTiles(e,i){const t=[];for(const s of this._tiles.values())this._addPlaceholderChild(t,s,e,i);const l=t.reduce(a,0);Math.abs(1-l)<n||this._addPlaceholderParent(e.id,i)}_addPlaceholderChild(e,i,t,l){i.key.level<=t.level||!i.hasData()||d(t,i.key)&&(this._addToContainer(i),l.add(i.id),e.push(i.key.level-t.level))}_addPlaceholderParent(e,i){const t=this._tiles;let l=e;for(;;){if(l=c(l),!l||i.has(l))return;const e=t.get(l);if(e?.hasData())return this._addToContainer(e),void i.add(e.id)}}_getOrAcquireTile(e){let i=this._tiles.get(e);return i||(i=this._tileCache.pop(e),i||(i=this.acquireTile(new o(e))),this._tiles.set(e,i),i)}_releaseTile(e){const i=this._tiles.get(e);this.releaseTile(i),this._removeFromContainer(i),this._tiles.delete(e),i.hasData()?this._tileCache.put(e,i,1):i.dispose()}_addToContainer(e){let i;const t=[],l=this._container;if(l.contains(e))return;const s=this._visibleTiles;for(const o of s.values())this._canConnectDirectly(e,o)&&t.push(o),null==i&&this._canConnectDirectly(o,e)&&(i=o);if(null!=i){for(const l of t)i.childrenTiles.delete(l),e.childrenTiles.add(l),l.parentTile=e;i.childrenTiles.add(e),e.parentTile=i}else for(const o of t)e.childrenTiles.add(o),o.parentTile=e;s.set(e.id,e),l.addChild(e)}_removeFromContainer(e){if(this._visibleTiles.delete(e.id),this._container.removeChild(e),null!=e.parentTile){e.parentTile.childrenTiles.delete(e);for(const i of e.childrenTiles)null!=e.parentTile&&e.parentTile.childrenTiles.add(i)}for(const i of e.childrenTiles)i.parentTile=e.parentTile;e.parentTile=null,e.childrenTiles.clear()}_canConnectDirectly(e,i){const t=e.key;let{level:l,row:s,col:o,world:r}=i.key;const n=this._visibleTiles;for(;l>0;){if(l--,s>>=1,o>>=1,t.level===l&&t.row===s&&t.col===o&&t.world===r)return!0;if(n.has(`${l}/${s}/${o}/${r}`))return!1}return!1}_updateCacheSize(e){const i=e.state.size;if(i[0]===this._viewSize[0]&&i[1]===this._viewSize[1])return;const t=Math.ceil(i[0]/r)+1,l=Math.ceil(i[1]/r)+1;this._viewSize[0]=i[0],this._viewSize[1]=i[1],this._tileCache.maxSize=5*t*l}}function c(e){const[i,t,l,s]=e.split("/"),o=parseInt(i,10);return 0===o?null:`${o-1}/${parseInt(t,10)>>1}/${parseInt(l,10)>>1}/${parseInt(s,10)}`}function d(e,i){const t=i.level-e.level;return e.row===i.row>>t&&e.col===i.col>>t&&e.world===i.world}export{h as TileManager};