import FilteredLayer from "../../../Models/FilteredLayer"; import {FeatureSourceForLayer, Tiled} from "../FeatureSource"; import {UIEventSource} from "../../UIEventSource"; import TileHierarchy from "./TileHierarchy"; import {Tiles} from "../../../Models/TileRange"; import {BBox} from "../../BBox"; /*** * A tiled source which dynamically loads the required tiles at a fixed zoom level */ export default class DynamicTileSource implements TileHierarchy { public readonly loadedTiles: Map; private readonly _loadedTiles = new Set(); constructor( layer: FilteredLayer, zoomlevel: number, constructTile: (zxy: [number, number, number]) => (FeatureSourceForLayer & Tiled), state: { currentBounds: UIEventSource; locationControl?: UIEventSource<{zoom?: number}> } ) { const self = this; this.loadedTiles = new Map() const neededTiles = state.currentBounds.map( bounds => { if (bounds === undefined) { // We'll retry later return undefined } if (!layer.isDisplayed.data && !layer.layerDef.forceLoad) { // No need to download! - the layer is disabled return undefined; } if (state.locationControl?.data?.zoom !== undefined && state.locationControl.data.zoom < layer.layerDef.minzoom) { // No need to download! - the layer is disabled return undefined; } const tileRange = Tiles.TileRangeBetween(zoomlevel, bounds.getNorth(), bounds.getEast(), bounds.getSouth(), bounds.getWest()) if (tileRange.total > 10000) { console.error("Got a really big tilerange, bounds and location might be out of sync") return undefined } const needed = Tiles.MapRange(tileRange, (x, y) => Tiles.tile_index(zoomlevel, x, y)).filter(i => !self._loadedTiles.has(i)) if (needed.length === 0) { return undefined } return needed } , [layer.isDisplayed, state.locationControl]).stabilized(250); neededTiles.addCallbackAndRunD(neededIndexes => { console.log("Tiled geojson source ", layer.layerDef.id, " needs", neededIndexes) if (neededIndexes === undefined) { return; } for (const neededIndex of neededIndexes) { self._loadedTiles.add(neededIndex) const src = constructTile(Tiles.tile_from_index(neededIndex)) if (src !== undefined) { self.loadedTiles.set(neededIndex, src) } } }) } }