import { Layer_default2 as Layer_default } from "./chunk-ZUI5NXIU.js"; import { Layer_default as Layer_default2 } from "./chunk-I6K7MRGV.js"; import { ImageTile_default, TileRange_default, Tile_default, Tile_default2, createOrUpdate2 as createOrUpdate, getCacheKey } from "./chunk-7XMWB3J4.js"; import { TileState_default } from "./chunk-5D2XPBR2.js"; import { toSize } from "./chunk-SHUBVYN4.js"; import { apply, compose } from "./chunk-X52LGBOS.js"; import { assert } from "./chunk-QFCIXVZ3.js"; import { equivalent, fromUserExtent } from "./chunk-A3RXLHYB.js"; import { createCanvasContext2D } from "./chunk-UPTVWZ45.js"; import { getUid } from "./chunk-Q5ZULJHM.js"; import { Disposable_default } from "./chunk-NGFXCWUF.js"; import { ascending } from "./chunk-K25ZO44T.js"; import { containsCoordinate, createEmpty, equals, getIntersection, getRotatedViewport, getTopLeft, intersects } from "./chunk-SRXHWJOY.js"; // node_modules/ol/DataTile.js function asImageLike(data) { return data instanceof Image || data instanceof HTMLCanvasElement || data instanceof HTMLVideoElement || data instanceof ImageBitmap ? data : null; } function asArrayLike(data) { return data instanceof Uint8Array || data instanceof Uint8ClampedArray || data instanceof Float32Array || data instanceof DataView ? data : null; } var disposedError = new Error("disposed"); var sharedContext = null; function toArray(image) { if (!sharedContext) { sharedContext = createCanvasContext2D( image.width, image.height, void 0, { willReadFrequently: true } ); } const canvas = sharedContext.canvas; const width = image.width; if (canvas.width !== width) { canvas.width = width; } const height = image.height; if (canvas.height !== height) { canvas.height = height; } sharedContext.clearRect(0, 0, width, height); sharedContext.drawImage(image, 0, 0); return sharedContext.getImageData(0, 0, width, height).data; } var defaultSize = [256, 256]; var DataTile = class extends Tile_default { /** * @param {Options} options Tile options. */ constructor(options) { const state = TileState_default.IDLE; super(options.tileCoord, state, { transition: options.transition, interpolate: options.interpolate }); this.loader_ = options.loader; this.data_ = null; this.error_ = null; this.size_ = options.size || null; this.controller_ = options.controller || null; } /** * Get the tile size. * @return {import('./size.js').Size} Tile size. */ getSize() { if (this.size_) { return this.size_; } const imageData = asImageLike(this.data_); if (imageData) { return [imageData.width, imageData.height]; } return defaultSize; } /** * Get the data for the tile. * @return {Data} Tile data. * @api */ getData() { return this.data_; } /** * Get any loading error. * @return {Error} Loading error. * @api */ getError() { return this.error_; } /** * Load the tile data. * @api * @override */ load() { if (this.state !== TileState_default.IDLE && this.state !== TileState_default.ERROR) { return; } this.state = TileState_default.LOADING; this.changed(); const self = this; this.loader_().then(function(data) { self.data_ = data; self.state = TileState_default.LOADED; self.changed(); }).catch(function(error) { self.error_ = error; self.state = TileState_default.ERROR; self.changed(); }); } /** * Clean up. * @override */ disposeInternal() { if (this.controller_) { this.controller_.abort(disposedError); this.controller_ = null; } super.disposeInternal(); } }; var DataTile_default = DataTile; // node_modules/ol/structs/LRUCache.js var LRUCache = class { /** * @param {number} [highWaterMark] High water mark. */ constructor(highWaterMark) { this.highWaterMark = highWaterMark !== void 0 ? highWaterMark : 2048; this.count_ = 0; this.entries_ = {}; this.oldest_ = null; this.newest_ = null; } deleteOldest() { const entry = this.pop(); if (entry instanceof Disposable_default) { entry.dispose(); } } /** * @return {boolean} Can expire cache. */ canExpireCache() { return this.highWaterMark > 0 && this.getCount() > this.highWaterMark; } /** * Expire the cache. When the cache entry is a {@link module:ol/Disposable~Disposable}, * the entry will be disposed. * @param {!Object} [keep] Keys to keep. To be implemented by subclasses. */ expireCache(keep) { while (this.canExpireCache()) { this.deleteOldest(); } } /** * FIXME empty description for jsdoc */ clear() { while (this.oldest_) { this.deleteOldest(); } } /** * @param {string} key Key. * @return {boolean} Contains key. */ containsKey(key) { return this.entries_.hasOwnProperty(key); } /** * @param {function(T, string, LRUCache): ?} f The function * to call for every entry from the oldest to the newer. This function takes * 3 arguments (the entry value, the entry key and the LRUCache object). * The return value is ignored. */ forEach(f) { let entry = this.oldest_; while (entry) { f(entry.value_, entry.key_, this); entry = entry.newer; } } /** * @param {string} key Key. * @param {*} [options] Options (reserved for subclasses). * @return {T} Value. */ get(key, options) { const entry = this.entries_[key]; assert( entry !== void 0, "Tried to get a value for a key that does not exist in the cache" ); if (entry === this.newest_) { return entry.value_; } if (entry === this.oldest_) { this.oldest_ = /** @type {Entry} */ this.oldest_.newer; this.oldest_.older = null; } else { entry.newer.older = entry.older; entry.older.newer = entry.newer; } entry.newer = null; entry.older = this.newest_; this.newest_.newer = entry; this.newest_ = entry; return entry.value_; } /** * Remove an entry from the cache. * @param {string} key The entry key. * @return {T} The removed entry. */ remove(key) { const entry = this.entries_[key]; assert( entry !== void 0, "Tried to get a value for a key that does not exist in the cache" ); if (entry === this.newest_) { this.newest_ = /** @type {Entry} */ entry.older; if (this.newest_) { this.newest_.newer = null; } } else if (entry === this.oldest_) { this.oldest_ = /** @type {Entry} */ entry.newer; if (this.oldest_) { this.oldest_.older = null; } } else { entry.newer.older = entry.older; entry.older.newer = entry.newer; } delete this.entries_[key]; --this.count_; return entry.value_; } /** * @return {number} Count. */ getCount() { return this.count_; } /** * @return {Array} Keys. */ getKeys() { const keys = new Array(this.count_); let i = 0; let entry; for (entry = this.newest_; entry; entry = entry.older) { keys[i++] = entry.key_; } return keys; } /** * @return {Array} Values. */ getValues() { const values = new Array(this.count_); let i = 0; let entry; for (entry = this.newest_; entry; entry = entry.older) { values[i++] = entry.value_; } return values; } /** * @return {T} Last value. */ peekLast() { return this.oldest_.value_; } /** * @return {string} Last key. */ peekLastKey() { return this.oldest_.key_; } /** * Get the key of the newest item in the cache. Throws if the cache is empty. * @return {string} The newest key. */ peekFirstKey() { return this.newest_.key_; } /** * Return an entry without updating least recently used time. * @param {string} key Key. * @return {T|undefined} Value. */ peek(key) { var _a; return (_a = this.entries_[key]) == null ? void 0 : _a.value_; } /** * @return {T} value Value. */ pop() { const entry = this.oldest_; delete this.entries_[entry.key_]; if (entry.newer) { entry.newer.older = null; } this.oldest_ = /** @type {Entry} */ entry.newer; if (!this.oldest_) { this.newest_ = null; } --this.count_; return entry.value_; } /** * @param {string} key Key. * @param {T} value Value. */ replace(key, value) { this.get(key); this.entries_[key].value_ = value; } /** * @param {string} key Key. * @param {T} value Value. */ set(key, value) { assert( !(key in this.entries_), "Tried to set a value for a key that is used already" ); const entry = { key_: key, newer: null, older: this.newest_, value_: value }; if (!this.newest_) { this.oldest_ = entry; } else { this.newest_.newer = entry; } this.newest_ = entry; this.entries_[key] = entry; ++this.count_; } /** * Set a maximum number of entries for the cache. * @param {number} size Cache size. * @api */ setSize(size) { this.highWaterMark = size; } }; var LRUCache_default = LRUCache; // node_modules/ol/renderer/canvas/TileLayer.js function addTileToLookup(tilesByZ, tile, z) { if (!(z in tilesByZ)) { tilesByZ[z] = /* @__PURE__ */ new Set([tile]); return true; } const set = tilesByZ[z]; const existing = set.has(tile); if (!existing) { set.add(tile); } return !existing; } function removeTileFromLookup(tilesByZ, tile, z) { const set = tilesByZ[z]; if (set) { return set.delete(tile); } return false; } function getRenderExtent(frameState, extent) { const layerState = frameState.layerStatesArray[frameState.layerIndex]; if (layerState.extent) { extent = getIntersection( extent, fromUserExtent(layerState.extent, frameState.viewState.projection) ); } const source = ( /** @type {import("../../source/Tile.js").default} */ layerState.layer.getRenderSource() ); if (!source.getWrapX()) { const gridExtent = source.getTileGridForProjection(frameState.viewState.projection).getExtent(); if (gridExtent) { extent = getIntersection(extent, gridExtent); } } return extent; } var CanvasTileLayerRenderer = class extends Layer_default { /** * @param {LayerType} tileLayer Tile layer. * @param {Options} [options] Options. */ constructor(tileLayer, options) { super(tileLayer); options = options || {}; this.extentChanged = true; this.renderComplete = false; this.renderedExtent_ = null; this.renderedPixelRatio; this.renderedProjection = null; this.renderedTiles = []; this.renderedSourceKey_; this.renderedSourceRevision_; this.tempExtent = createEmpty(); this.tempTileRange_ = new TileRange_default(0, 0, 0, 0); this.tempTileCoord_ = createOrUpdate(0, 0, 0); const cacheSize = options.cacheSize !== void 0 ? options.cacheSize : 512; this.tileCache_ = new LRUCache_default(cacheSize); this.sourceTileCache_ = null; this.maxStaleKeys = cacheSize * 0.5; } /** * @return {LRUCache} Tile cache. */ getTileCache() { return this.tileCache_; } /** * @return {LRUCache} Tile cache. */ getSourceTileCache() { if (!this.sourceTileCache_) { this.sourceTileCache_ = new LRUCache_default(512); } return this.sourceTileCache_; } /** * Get a tile from the cache or create one if needed. * * @param {number} z Tile coordinate z. * @param {number} x Tile coordinate x. * @param {number} y Tile coordinate y. * @param {import("../../Map.js").FrameState} frameState Frame state. * @return {import("../../Tile.js").default|null} Tile (or null if outside source extent). * @protected */ getOrCreateTile(z, x, y, frameState) { const tileCache = this.tileCache_; const tileLayer = this.getLayer(); const tileSource = tileLayer.getSource(); const cacheKey = getCacheKey(tileSource, tileSource.getKey(), z, x, y); let tile; if (tileCache.containsKey(cacheKey)) { tile = tileCache.get(cacheKey); } else { const projection = frameState.viewState.projection; const sourceProjection = tileSource.getProjection(); tile = tileSource.getTile( z, x, y, frameState.pixelRatio, projection, !sourceProjection || equivalent(sourceProjection, projection) ? void 0 : this.getSourceTileCache() ); if (!tile) { return null; } tileCache.set(cacheKey, tile); } return tile; } /** * @param {number} z Tile coordinate z. * @param {number} x Tile coordinate x. * @param {number} y Tile coordinate y. * @param {import("../../Map.js").FrameState} frameState Frame state. * @return {import("../../Tile.js").default|null} Tile (or null if outside source extent). * @protected */ getTile(z, x, y, frameState) { const tile = this.getOrCreateTile(z, x, y, frameState); if (!tile) { return null; } return tile; } /** * @param {import("../../pixel.js").Pixel} pixel Pixel. * @return {Uint8ClampedArray} Data at the pixel location. * @override */ getData(pixel) { const frameState = this.frameState; if (!frameState) { return null; } const layer = this.getLayer(); const coordinate = apply( frameState.pixelToCoordinateTransform, pixel.slice() ); const layerExtent = layer.getExtent(); if (layerExtent) { if (!containsCoordinate(layerExtent, coordinate)) { return null; } } const viewState = frameState.viewState; const source = layer.getRenderSource(); const tileGrid = source.getTileGridForProjection(viewState.projection); const tilePixelRatio = source.getTilePixelRatio(frameState.pixelRatio); for (let z = tileGrid.getZForResolution(viewState.resolution); z >= tileGrid.getMinZoom(); --z) { const tileCoord = tileGrid.getTileCoordForCoordAndZ(coordinate, z); const tile = this.getTile(z, tileCoord[1], tileCoord[2], frameState); if (!tile || tile.getState() !== TileState_default.LOADED) { continue; } const tileOrigin = tileGrid.getOrigin(z); const tileSize = toSize(tileGrid.getTileSize(z)); const tileResolution = tileGrid.getResolution(z); let image; if (tile instanceof ImageTile_default || tile instanceof Tile_default2) { image = tile.getImage(); } else if (tile instanceof DataTile_default) { image = asImageLike(tile.getData()); if (!image) { continue; } } else { continue; } const col = Math.floor( tilePixelRatio * ((coordinate[0] - tileOrigin[0]) / tileResolution - tileCoord[1] * tileSize[0]) ); const row = Math.floor( tilePixelRatio * ((tileOrigin[1] - coordinate[1]) / tileResolution - tileCoord[2] * tileSize[1]) ); const gutter = Math.round( tilePixelRatio * source.getGutterForProjection(viewState.projection) ); return this.getImageData(image, col + gutter, row + gutter); } return null; } /** * Determine whether render should be called. * @param {import("../../Map.js").FrameState} frameState Frame state. * @return {boolean} Layer is ready to be rendered. * @override */ prepareFrame(frameState) { var _a; if (!this.renderedProjection) { this.renderedProjection = frameState.viewState.projection; } else if (frameState.viewState.projection !== this.renderedProjection) { this.tileCache_.clear(); this.renderedProjection = frameState.viewState.projection; } const source = this.getLayer().getSource(); if (!source) { return false; } const sourceRevision = source.getRevision(); if (!this.renderedSourceRevision_) { this.renderedSourceRevision_ = sourceRevision; } else if (this.renderedSourceRevision_ !== sourceRevision) { this.renderedSourceRevision_ = sourceRevision; if (this.renderedSourceKey_ === source.getKey()) { this.tileCache_.clear(); (_a = this.sourceTileCache_) == null ? void 0 : _a.clear(); } } return true; } /** * Determine whether tiles for next extent should be enqueued for rendering. * @return {boolean} Rendering tiles for next extent is supported. * @protected */ enqueueTilesForNextExtent() { return true; } /** * @param {import("../../Map.js").FrameState} frameState Frame state. * @param {import("../../extent.js").Extent} extent The extent to be rendered. * @param {number} initialZ The zoom level. * @param {TileLookup} tilesByZ Lookup of tiles by zoom level. * @param {number} preload Number of additional levels to load. */ enqueueTiles(frameState, extent, initialZ, tilesByZ, preload) { const viewState = frameState.viewState; const tileLayer = this.getLayer(); const tileSource = tileLayer.getRenderSource(); const tileGrid = tileSource.getTileGridForProjection(viewState.projection); const tileSourceKey = getUid(tileSource); if (!(tileSourceKey in frameState.wantedTiles)) { frameState.wantedTiles[tileSourceKey] = {}; } const wantedTiles = frameState.wantedTiles[tileSourceKey]; const map = tileLayer.getMapInternal(); const minZ = Math.max( initialZ - preload, tileGrid.getMinZoom(), tileGrid.getZForResolution( Math.min( tileLayer.getMaxResolution(), map ? map.getView().getResolutionForZoom(Math.max(tileLayer.getMinZoom(), 0)) : tileGrid.getResolution(0) ), tileSource.zDirection ) ); const rotation = viewState.rotation; const viewport = rotation ? getRotatedViewport( viewState.center, viewState.resolution, rotation, frameState.size ) : void 0; for (let z = initialZ; z >= minZ; --z) { const tileRange = tileGrid.getTileRangeForExtentAndZ( extent, z, this.tempTileRange_ ); const tileResolution = tileGrid.getResolution(z); for (let x = tileRange.minX; x <= tileRange.maxX; ++x) { for (let y = tileRange.minY; y <= tileRange.maxY; ++y) { if (rotation && !tileGrid.tileCoordIntersectsViewport([z, x, y], viewport)) { continue; } const tile = this.getTile(z, x, y, frameState); if (!tile) { continue; } const added = addTileToLookup(tilesByZ, tile, z); if (!added) { continue; } const tileQueueKey = tile.getKey(); wantedTiles[tileQueueKey] = true; if (tile.getState() === TileState_default.IDLE) { if (!frameState.tileQueue.isKeyQueued(tileQueueKey)) { const tileCoord = createOrUpdate(z, x, y, this.tempTileCoord_); frameState.tileQueue.enqueue([ tile, tileSourceKey, tileGrid.getTileCoordCenter(tileCoord), tileResolution ]); } } } } } } /** * Look for tiles covering the provided tile coordinate at an alternate * zoom level. Loaded tiles will be added to the provided tile texture lookup. * @param {import("../../tilecoord.js").TileCoord} tileCoord The target tile coordinate. * @param {TileLookup} tilesByZ Lookup of tiles by zoom level. * @return {boolean} The tile coordinate is covered by loaded tiles at the alternate zoom level. * @private */ findStaleTile_(tileCoord, tilesByZ) { const tileCache = this.tileCache_; const z = tileCoord[0]; const x = tileCoord[1]; const y = tileCoord[2]; const staleKeys = this.getStaleKeys(); for (let i = 0; i < staleKeys.length; ++i) { const cacheKey = getCacheKey( this.getLayer().getSource(), staleKeys[i], z, x, y ); if (tileCache.containsKey(cacheKey)) { const tile = tileCache.peek(cacheKey); if (tile.getState() === TileState_default.LOADED) { tile.endTransition(getUid(this)); addTileToLookup(tilesByZ, tile, z); return true; } } } return false; } /** * Look for tiles covering the provided tile coordinate at an alternate * zoom level. Loaded tiles will be added to the provided tile texture lookup. * @param {import("../../tilegrid/TileGrid.js").default} tileGrid The tile grid. * @param {import("../../tilecoord.js").TileCoord} tileCoord The target tile coordinate. * @param {number} altZ The alternate zoom level. * @param {TileLookup} tilesByZ Lookup of tiles by zoom level. * @return {boolean} The tile coordinate is covered by loaded tiles at the alternate zoom level. * @private */ findAltTiles_(tileGrid, tileCoord, altZ, tilesByZ) { const tileRange = tileGrid.getTileRangeForTileCoordAndZ( tileCoord, altZ, this.tempTileRange_ ); if (!tileRange) { return false; } let covered = true; const tileCache = this.tileCache_; const source = this.getLayer().getRenderSource(); const sourceKey = source.getKey(); for (let x = tileRange.minX; x <= tileRange.maxX; ++x) { for (let y = tileRange.minY; y <= tileRange.maxY; ++y) { const cacheKey = getCacheKey(source, sourceKey, altZ, x, y); let loaded = false; if (tileCache.containsKey(cacheKey)) { const tile = tileCache.peek(cacheKey); if (tile.getState() === TileState_default.LOADED) { addTileToLookup(tilesByZ, tile, altZ); loaded = true; } } if (!loaded) { covered = false; } } } return covered; } /** * Render the layer. * * The frame rendering logic has three parts: * * 1. Enqueue tiles * 2. Find alt tiles for those that are not yet loaded * 3. Render loaded tiles * * @param {import("../../Map.js").FrameState} frameState Frame state. * @param {HTMLElement} target Target that may be used to render content to. * @return {HTMLElement} The rendered element. * @override */ renderFrame(frameState, target) { this.renderComplete = true; const layerState = frameState.layerStatesArray[frameState.layerIndex]; const viewState = frameState.viewState; const projection = viewState.projection; const viewResolution = viewState.resolution; const viewCenter = viewState.center; const pixelRatio = frameState.pixelRatio; const tileLayer = this.getLayer(); const tileSource = tileLayer.getSource(); const tileGrid = tileSource.getTileGridForProjection(projection); const z = tileGrid.getZForResolution(viewResolution, tileSource.zDirection); const tileResolution = tileGrid.getResolution(z); const sourceKey = tileSource.getKey(); if (!this.renderedSourceKey_) { this.renderedSourceKey_ = sourceKey; } else if (this.renderedSourceKey_ !== sourceKey) { this.prependStaleKey(this.renderedSourceKey_); this.renderedSourceKey_ = sourceKey; } let frameExtent = frameState.extent; const tilePixelRatio = tileSource.getTilePixelRatio(pixelRatio); this.prepareContainer(frameState, target); const width = this.context.canvas.width; const height = this.context.canvas.height; const layerExtent = layerState.extent && fromUserExtent(layerState.extent, projection); if (layerExtent) { frameExtent = getIntersection( frameExtent, fromUserExtent(layerState.extent, projection) ); } const dx = tileResolution * width / 2 / tilePixelRatio; const dy = tileResolution * height / 2 / tilePixelRatio; const canvasExtent = [ viewCenter[0] - dx, viewCenter[1] - dy, viewCenter[0] + dx, viewCenter[1] + dy ]; const tilesByZ = {}; this.renderedTiles.length = 0; const preload = tileLayer.getPreload(); if (frameState.nextExtent && this.enqueueTilesForNextExtent()) { const targetZ = tileGrid.getZForResolution( viewState.nextResolution, tileSource.zDirection ); const nextExtent = getRenderExtent(frameState, frameState.nextExtent); this.enqueueTiles(frameState, nextExtent, targetZ, tilesByZ, preload); } const renderExtent = getRenderExtent(frameState, frameExtent); this.enqueueTiles(frameState, renderExtent, z, tilesByZ, 0); if (preload > 0) { setTimeout(() => { this.enqueueTiles( frameState, renderExtent, z - 1, tilesByZ, preload - 1 ); }, 0); } if (!(z in tilesByZ)) { return this.container; } const uid = getUid(this); const time = frameState.time; for (const tile of tilesByZ[z]) { const tileState = tile.getState(); if (tileState === TileState_default.EMPTY) { continue; } const tileCoord = tile.tileCoord; if (tileState === TileState_default.LOADED) { const alpha = tile.getAlpha(uid, time); if (alpha === 1) { tile.endTransition(uid); continue; } } if (tileState !== TileState_default.ERROR) { this.renderComplete = false; } const hasStaleTile = this.findStaleTile_(tileCoord, tilesByZ); if (hasStaleTile) { removeTileFromLookup(tilesByZ, tile, z); frameState.animate = true; continue; } const coveredByChildren = this.findAltTiles_( tileGrid, tileCoord, z + 1, tilesByZ ); if (coveredByChildren) { continue; } const minZoom = tileGrid.getMinZoom(); for (let parentZ = z - 1; parentZ >= minZoom; --parentZ) { const coveredByParent = this.findAltTiles_( tileGrid, tileCoord, parentZ, tilesByZ ); if (coveredByParent) { break; } } } const canvasScale = tileResolution / viewResolution * pixelRatio / tilePixelRatio; const context = this.getRenderContext(frameState); compose( this.tempTransform, width / 2, height / 2, canvasScale, canvasScale, 0, -width / 2, -height / 2 ); if (layerState.extent) { this.clipUnrotated(context, frameState, layerExtent); } if (!tileSource.getInterpolate()) { context.imageSmoothingEnabled = false; } this.preRender(context, frameState); const zs = Object.keys(tilesByZ).map(Number); zs.sort(ascending); let currentClip; const clips = []; const clipZs = []; for (let i = zs.length - 1; i >= 0; --i) { const currentZ = zs[i]; const currentTilePixelSize = tileSource.getTilePixelSize( currentZ, pixelRatio, projection ); const currentResolution = tileGrid.getResolution(currentZ); const currentScale = currentResolution / tileResolution; const dx2 = currentTilePixelSize[0] * currentScale * canvasScale; const dy2 = currentTilePixelSize[1] * currentScale * canvasScale; const originTileCoord = tileGrid.getTileCoordForCoordAndZ( getTopLeft(canvasExtent), currentZ ); const originTileExtent = tileGrid.getTileCoordExtent(originTileCoord); const origin = apply(this.tempTransform, [ tilePixelRatio * (originTileExtent[0] - canvasExtent[0]) / tileResolution, tilePixelRatio * (canvasExtent[3] - originTileExtent[3]) / tileResolution ]); const tileGutter = tilePixelRatio * tileSource.getGutterForProjection(projection); for (const tile of tilesByZ[currentZ]) { if (tile.getState() !== TileState_default.LOADED) { continue; } const tileCoord = tile.tileCoord; const xIndex = originTileCoord[1] - tileCoord[1]; const nextX = Math.round(origin[0] - (xIndex - 1) * dx2); const yIndex = originTileCoord[2] - tileCoord[2]; const nextY = Math.round(origin[1] - (yIndex - 1) * dy2); const x = Math.round(origin[0] - xIndex * dx2); const y = Math.round(origin[1] - yIndex * dy2); const w = nextX - x; const h = nextY - y; const transition = zs.length === 1; let contextSaved = false; currentClip = [x, y, x + w, y, x + w, y + h, x, y + h]; for (let i2 = 0, ii = clips.length; i2 < ii; ++i2) { if (!transition && currentZ < clipZs[i2]) { const clip = clips[i2]; if (intersects( [x, y, x + w, y + h], [clip[0], clip[3], clip[4], clip[7]] )) { if (!contextSaved) { context.save(); contextSaved = true; } context.beginPath(); context.moveTo(currentClip[0], currentClip[1]); context.lineTo(currentClip[2], currentClip[3]); context.lineTo(currentClip[4], currentClip[5]); context.lineTo(currentClip[6], currentClip[7]); context.moveTo(clip[6], clip[7]); context.lineTo(clip[4], clip[5]); context.lineTo(clip[2], clip[3]); context.lineTo(clip[0], clip[1]); context.clip(); } } } clips.push(currentClip); clipZs.push(currentZ); this.drawTile(tile, frameState, x, y, w, h, tileGutter, transition); if (contextSaved) { context.restore(); } this.renderedTiles.unshift(tile); this.updateUsedTiles(frameState.usedTiles, tileSource, tile); } } this.renderedResolution = tileResolution; this.extentChanged = !this.renderedExtent_ || !equals(this.renderedExtent_, canvasExtent); this.renderedExtent_ = canvasExtent; this.renderedPixelRatio = pixelRatio; this.postRender(this.context, frameState); if (layerState.extent) { context.restore(); } context.imageSmoothingEnabled = true; if (this.renderComplete) { const postRenderFunction = (map, frameState2) => { var _a; const tileSourceKey = getUid(tileSource); const wantedTiles = frameState2.wantedTiles[tileSourceKey]; const tilesCount = wantedTiles ? Object.keys(wantedTiles).length : 0; this.updateCacheSize(tilesCount); this.tileCache_.expireCache(); (_a = this.sourceTileCache_) == null ? void 0 : _a.expireCache(); }; frameState.postRenderFunctions.push(postRenderFunction); } return this.container; } /** * Increases the cache size if needed * @param {number} tileCount Minimum number of tiles needed. */ updateCacheSize(tileCount) { this.tileCache_.highWaterMark = Math.max( this.tileCache_.highWaterMark, tileCount * 2 ); } /** * @param {import("../../Tile.js").default} tile Tile. * @param {import("../../Map.js").FrameState} frameState Frame state. * @param {number} x Left of the tile. * @param {number} y Top of the tile. * @param {number} w Width of the tile. * @param {number} h Height of the tile. * @param {number} gutter Tile gutter. * @param {boolean} transition Apply an alpha transition. * @protected */ drawTile(tile, frameState, x, y, w, h, gutter, transition) { let image; if (tile instanceof DataTile_default) { image = asImageLike(tile.getData()); if (!image) { throw new Error("Rendering array data is not yet supported"); } } else { image = this.getTileImage( /** @type {import("../../ImageTile.js").default} */ tile ); } if (!image) { return; } const context = this.getRenderContext(frameState); const uid = getUid(this); const layerState = frameState.layerStatesArray[frameState.layerIndex]; const alpha = layerState.opacity * (transition ? tile.getAlpha(uid, frameState.time) : 1); const alphaChanged = alpha !== context.globalAlpha; if (alphaChanged) { context.save(); context.globalAlpha = alpha; } context.drawImage( image, gutter, gutter, image.width - 2 * gutter, image.height - 2 * gutter, x, y, w, h ); if (alphaChanged) { context.restore(); } if (alpha !== layerState.opacity) { frameState.animate = true; } else if (transition) { tile.endTransition(uid); } } /** * @return {HTMLCanvasElement|OffscreenCanvas} Image */ getImage() { const context = this.context; return context ? context.canvas : null; } /** * Get the image from a tile. * @param {import("../../ImageTile.js").default} tile Tile. * @return {HTMLCanvasElement|OffscreenCanvas|HTMLImageElement|HTMLVideoElement} Image. * @protected */ getTileImage(tile) { return tile.getImage(); } /** * @param {!Object>} usedTiles Used tiles. * @param {import("../../source/Tile.js").default} tileSource Tile source. * @param {import('../../Tile.js').default} tile Tile. * @protected */ updateUsedTiles(usedTiles, tileSource, tile) { const tileSourceKey = getUid(tileSource); if (!(tileSourceKey in usedTiles)) { usedTiles[tileSourceKey] = {}; } usedTiles[tileSourceKey][tile.getKey()] = true; } }; var TileLayer_default = CanvasTileLayerRenderer; // node_modules/ol/layer/TileProperty.js var TileProperty_default = { PRELOAD: "preload", USE_INTERIM_TILES_ON_ERROR: "useInterimTilesOnError" }; // node_modules/ol/layer/BaseTile.js var BaseTileLayer = class extends Layer_default2 { /** * @param {Options} [options] Tile layer options. */ constructor(options) { options = options ? options : {}; const baseOptions = Object.assign({}, options); const cacheSize = options.cacheSize; delete options.cacheSize; delete baseOptions.preload; delete baseOptions.useInterimTilesOnError; super(baseOptions); this.on; this.once; this.un; this.cacheSize_ = cacheSize; this.setPreload(options.preload !== void 0 ? options.preload : 0); this.setUseInterimTilesOnError( options.useInterimTilesOnError !== void 0 ? options.useInterimTilesOnError : true ); } /** * @return {number|undefined} The suggested cache size * @protected */ getCacheSize() { return this.cacheSize_; } /** * Return the level as number to which we will preload tiles up to. * @return {number} The level to preload tiles up to. * @observable * @api */ getPreload() { return ( /** @type {number} */ this.get(TileProperty_default.PRELOAD) ); } /** * Set the level as number to which we will preload tiles up to. * @param {number} preload The level to preload tiles up to. * @observable * @api */ setPreload(preload) { this.set(TileProperty_default.PRELOAD, preload); } /** * Deprecated. Whether we use interim tiles on error. * @return {boolean} Use interim tiles on error. * @observable * @api */ getUseInterimTilesOnError() { return ( /** @type {boolean} */ this.get(TileProperty_default.USE_INTERIM_TILES_ON_ERROR) ); } /** * Deprecated. Set whether we use interim tiles on error. * @param {boolean} useInterimTilesOnError Use interim tiles on error. * @observable * @api */ setUseInterimTilesOnError(useInterimTilesOnError) { this.set(TileProperty_default.USE_INTERIM_TILES_ON_ERROR, useInterimTilesOnError); } /** * Get data for a pixel location. The return type depends on the source data. For image tiles, * a four element RGBA array will be returned. For data tiles, the array length will match the * number of bands in the dataset. For requests outside the layer extent, `null` will be returned. * Data for a image tiles can only be retrieved if the source's `crossOrigin` property is set. * * ```js * // display layer data on every pointer move * map.on('pointermove', (event) => { * console.log(layer.getData(event.pixel)); * }); * ``` * @param {import("../pixel").Pixel} pixel Pixel. * @return {Uint8ClampedArray|Uint8Array|Float32Array|DataView|null} Pixel data. * @api * @override */ getData(pixel) { return super.getData(pixel); } }; var BaseTile_default = BaseTileLayer; // node_modules/ol/layer/Tile.js var TileLayer = class extends BaseTile_default { /** * @param {import("./BaseTile.js").Options} [options] Tile layer options. */ constructor(options) { super(options); } /** * @override */ createRenderer() { return new TileLayer_default(this, { cacheSize: this.getCacheSize() }); } }; var Tile_default3 = TileLayer; export { asImageLike, asArrayLike, toArray, DataTile_default, LRUCache_default, TileLayer_default, TileProperty_default, BaseTile_default, Tile_default3 as Tile_default }; //# sourceMappingURL=chunk-UNDFRJ2M.js.map