@doegis/core
Version:
DOE GIS API
3 lines (1 loc) • 3.74 kB
JavaScript
import e from"../../../../core/LRUCache.js";import{isNone as i,isSome as t}from"../../../../core/maybe.js";import s from"../../tiling/TileCoverage.js";import l from"../../tiling/TileKey.js";const r=512,o=1e-6,n=(e,i)=>e+1/(1<<2*i);class a{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,i]of this._tiles)i.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,"smallest"),{spans:r,lodInfo:o}=t,{level:n}=o,a=this._tiles,c=new Set,h=new Set;for(const{row:s,colFrom:_,colTo:f}of r)for(let e=_;e<=f;e++){const i=l.getId(n,s,o.normalizeCol(e),o.getWorldForColumn(e)),t=this._getOrAcquireTile(i);c.add(i),t.processed()?this._addToContainer(t):h.add(new l(i))}for(const[s,l]of a)l.isCoverage=c.has(s);for(const s of h)this._findPlaceholdersForMissingTiles(s,c);let d=!1;for(const[s,l]of a)l.neededForCoverage=c.has(s),l.neededForCoverage||l.isHoldingForFade&&i.intersects(t,l.key)&&c.add(s),l.isFading&&(d=!0);for(const[s,l]of this._tiles)c.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()}_findPlaceholdersForMissingTiles(e,i){const t=[];for(const[l,r]of this._tiles)this._addPlaceholderChild(t,r,e,i);const s=t.reduce(n,0);Math.abs(1-s)<o||this._addPlaceholderParent(e.id,i)}_addPlaceholderChild(e,i,t,s){i.key.level<=t.level||!i.hasData()||h(t,i.key)&&(this._addToContainer(i),s.add(i.id),e.push(i.key.level-t.level))}_addPlaceholderParent(e,i){const t=this._tiles;let s=e;for(;;){if(s=c(s),!s||i.has(s))return;const e=t.get(s);if(e&&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 l(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 s;const l=[],r=this._container;if(r.contains(e))return;const o=this._visibleTiles;for(const[t,n]of o)this._canConnectDirectly(e,n)&&l.push(n),i(s)&&this._canConnectDirectly(n,e)&&(s=n);if(t(s)){for(const i of l)s.childrenTiles.delete(i),e.childrenTiles.add(i),i.parentTile=e;s.childrenTiles.add(e),e.parentTile=s}else for(const i of l)e.childrenTiles.add(i),i.parentTile=e;o.set(e.id,e),r.addChild(e)}_removeFromContainer(e){if(this._visibleTiles.delete(e.id),this._container.removeChild(e),t(e.parentTile)){e.parentTile.childrenTiles.delete(e);for(const i of e.childrenTiles)t(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:s,row:l,col:r,world:o}=i.key;const n=this._visibleTiles;for(;s>0;){if(s--,l>>=1,r>>=1,t.level===s&&t.row===l&&t.col===r&&t.world===o)return!0;if(n.has(`${s}/${l}/${r}/${o}`))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,s=Math.ceil(i[1]/r)+1;this._viewSize[0]=i[0],this._viewSize[1]=i[1],this._tileCache.maxSize=5*t*s}}function c(e){const[i,t,s,l]=e.split("/"),r=parseInt(i,10);return 0===r?null:`${r-1}/${parseInt(t,10)>>1}/${parseInt(s,10)>>1}/${parseInt(l,10)}`}function h(e,i){const t=i.level-e.level;return e.row===i.row>>t&&e.col===i.col>>t&&e.world===i.world}export{a as TileManager};