UNPKG

olcs

Version:

OpenLayers Cesium integration and plugin library

230 lines 17.7 kB
import MVT from 'ol/format/MVT.js'; import { get as getProjection } from 'ol/proj.js'; import { toContext } from 'ol/render.js'; import RenderFeature from 'ol/render/Feature.js'; import LRUCache from 'ol/structs/LRUCache.js'; import Stroke from 'ol/style/Stroke.js'; import Style, {} from 'ol/style/Style.js'; import { getForProjection as getTilegridForProjection } from 'ol/tilegrid.js'; import { createFromTemplates as createTileUrlFunctions } from 'ol/tileurlfunction.js'; import { createEmptyCanvas } from './core/OLImageryProvider.js'; const format = new MVT({ featureClass: RenderFeature, }); const styles = [ new Style({ stroke: new Stroke({ color: 'blue', width: 2, }), }), ]; export default class MVTImageryProvider { urls; emptyCanvas_ = createEmptyCanvas(); emptyCanvasPromise_ = Promise.resolve(this.emptyCanvas_); tilingScheme_ = new Cesium.WebMercatorTilingScheme(); ready_ = true; rectangle_; tileRectangle_; tileWidth = 256; tileHeight = 256; maximumLevel = 20; minimumLevel_ = 0; get minimumLevel() { return this.minimumLevel_; } featureCache; tileCache; tileFunction_; styleFunction_; projection_ = getProjection('EPSG:3857'); /** * When <code>true</code>, this model is ready to render, i.e., the external binary, image, * and shader files were downloaded and the WebGL resources were created. */ get ready() { return this.ready_; } /** * Gets the rectangle, in radians, of the imagery provided by the instance. */ get rectangle() { return this.rectangle_; } /** * Gets the tiling scheme used by the provider. */ get tilingScheme() { return this.tilingScheme_; } /** * Gets an event that is raised when the imagery provider encounters an asynchronous error. By subscribing * to the event, you will be notified of the error and can potentially recover from it. Event listeners * are passed an instance of {@link Cesium.TileProviderError}. */ errorEvent = new Cesium.Event(); /** * Gets the credit to display when this imagery provider is active. Typically this is used to credit * the source of the imagery. */ credit; getTileCredits(x, y, level) { return []; } /** * Gets the proxy used by this provider. */ proxy; get _ready() { return this.ready_; } /** * Gets the tile discard policy. If not undefined, the discard policy is responsible * for filtering out "missing" tiles via its shouldDiscardImage function. If this function * returns undefined, no tiles are filtered. */ get tileDiscardPolicy() { return undefined; } // FIXME: this might be exposed /** * Gets a value indicating whether or not the images provided by this imagery provider * include an alpha channel. If this property is false, an alpha channel, if present, will * be ignored. If this property is true, any images without an alpha channel will be treated * as if their alpha is 1.0 everywhere. When this property is false, memory usage * and texture upload time are reduced. */ get hasAlphaChannel() { return true; } // FIXME: this could be implemented by proxying to OL /** * Asynchronously determines what features, if any, are located at a given longitude and latitude within * a tile. * This function is optional, so it may not exist on all ImageryProviders. * @param x The tile X coordinate. * @param y The tile Y coordinate. * @param level The tile level. * @param longitude The longitude at which to pick features. * @param latitude The latitude at which to pick features. * @return A promise for the picked features that will resolve when the asynchronous * picking completes. The resolved value is an array of {@link ImageryLayerFeatureInfo} * instances. The array may be empty if no features are found at the given location. * It may also be undefined if picking is not supported. */ pickFeatures(x, y, level, longitude, latitude) { return undefined; } constructor(options) { this.urls = options.urls; this.rectangle_ = options.rectangle || this.tilingScheme.rectangle; this.credit = options.credit; this.styleFunction_ = options.styleFunction || (() => styles); this.tileRectangle_ = new Cesium.Rectangle(); // to avoid too frequent cache grooming we allow x2 capacity const cacheSize = options.cacheSize !== undefined ? options.cacheSize : 50; this.tileCache = new LRUCache(cacheSize); this.featureCache = options.featureCache || new LRUCache(cacheSize); this.minimumLevel_ = options.minimumLevel || 0; const tileGrid = getTilegridForProjection(this.projection_); this.tileFunction_ = createTileUrlFunctions(this.urls, tileGrid); } getTileFeatures(z, x, y) { const cacheKey = this.getCacheKey_(z, x, y); let promise; if (this.featureCache.containsKey(cacheKey)) { promise = this.featureCache.get(cacheKey); } if (!promise) { const url = this.getUrl_(z, x, y); promise = fetch(url) .then((r) => (r.ok ? r : Promise.reject(r))) .then((r) => r.arrayBuffer()) .then((buffer) => this.readFeaturesFromBuffer(buffer)); this.featureCache.set(cacheKey, promise); if (this.featureCache.getCount() > 2 * this.featureCache.highWaterMark) { while (this.featureCache.canExpireCache()) { this.featureCache.pop(); } } } return promise; } readFeaturesFromBuffer(buffer) { const features = format.readFeatures(buffer); const scaleFactor = this.tileWidth / 4096; features.forEach((f) => { const flatCoordinates = f.getFlatCoordinates(); for (let i = 0; i < flatCoordinates.length; ++i) { flatCoordinates[i] *= scaleFactor; } }); return features; } getUrl_(z, x, y) { // FIXME: probably we should not pass 1 as pixelRatio const url = this.tileFunction_([z, x, y], 1, this.projection_); return url; } getCacheKey_(z, x, y) { return `${z}_${x}_${y}`; } requestImage(x, y, z, request) { if (z < this.minimumLevel_) { return this.emptyCanvasPromise_; } try { const cacheKey = this.getCacheKey_(z, x, y); let promise; if (this.tileCache.containsKey(cacheKey)) { promise = this.tileCache.get(cacheKey); } if (!promise) { promise = this.getTileFeatures(z, x, y).then((features) => { // FIXME: here we suppose the 2D projection is in meters this.tilingScheme.tileXYToNativeRectangle(x, y, z, this.tileRectangle_); const resolution = (this.tileRectangle_.east - this.tileRectangle_.west) / this.tileWidth; return this.rasterizeFeatures(features, this.styleFunction_, resolution); }); this.tileCache.set(cacheKey, promise); if (this.tileCache.getCount() > 2 * this.tileCache.highWaterMark) { while (this.tileCache.canExpireCache()) { this.tileCache.pop(); } } } return promise; } catch (e) { console.trace(e); // FIXME: open PR on Cesium to fix incorrect typing // @ts-ignore this.errorEvent.raiseEvent('could not render pbf to tile', e); } } rasterizeFeatures(features, styleFunction, resolution) { const canvas = document.createElement('canvas'); const vectorContext = toContext(canvas.getContext('2d'), { size: [this.tileWidth, this.tileHeight], }); features.forEach((f) => { const styles = styleFunction(f, resolution); if (styles) { if (Array.isArray(styles)) { styles.forEach((style) => { vectorContext.setStyle(style); vectorContext.drawGeometry(f); }); } else { vectorContext.setStyle(styles); vectorContext.drawGeometry(f); } } }); return canvas; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTVZUSW1hZ2VyeVByb3ZpZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL29sY3MvTVZUSW1hZ2VyeVByb3ZpZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQWFBLE9BQU8sR0FBRyxNQUFNLGtCQUFrQixDQUFDO0FBQ25DLE9BQU8sRUFBQyxHQUFHLElBQUksYUFBYSxFQUFDLE1BQU0sWUFBWSxDQUFDO0FBQ2hELE9BQU8sRUFBQyxTQUFTLEVBQUMsTUFBTSxjQUFjLENBQUM7QUFDdkMsT0FBTyxhQUFhLE1BQU0sc0JBQXNCLENBQUM7QUFDakQsT0FBTyxRQUFRLE1BQU0sd0JBQXdCLENBQUM7QUFDOUMsT0FBTyxNQUFNLE1BQU0sb0JBQW9CLENBQUM7QUFDeEMsT0FBTyxLQUFLLEVBQUUsRUFBb0IsTUFBTSxtQkFBbUIsQ0FBQztBQUM1RCxPQUFPLEVBQUMsZ0JBQWdCLElBQUksd0JBQXdCLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUM1RSxPQUFPLEVBQUMsbUJBQW1CLElBQUksc0JBQXNCLEVBQUMsTUFBTSx1QkFBdUIsQ0FBQztBQUNwRixPQUFPLEVBQUMsaUJBQWlCLEVBQUMsTUFBTSw2QkFBNkIsQ0FBQztBQVk5RCxNQUFNLE1BQU0sR0FBRyxJQUFJLEdBQUcsQ0FBQztJQUNyQixZQUFZLEVBQUUsYUFBYTtDQUM1QixDQUFDLENBQUM7QUFFSCxNQUFNLE1BQU0sR0FBRztJQUNiLElBQUksS0FBSyxDQUFDO1FBQ1IsTUFBTSxFQUFFLElBQUksTUFBTSxDQUFDO1lBQ2pCLEtBQUssRUFBRSxNQUFNO1lBQ2IsS0FBSyxFQUFFLENBQUM7U0FDVCxDQUFDO0tBQ0gsQ0FBQztDQUNILENBQUM7QUFFRixNQUFNLENBQUMsT0FBTyxPQUFPLGtCQUFrQjtJQUM3QixJQUFJLENBQVc7SUFDZixZQUFZLEdBQXNCLGlCQUFpQixFQUFFLENBQUM7SUFDdEQsbUJBQW1CLEdBQStCLE9BQU8sQ0FBQyxPQUFPLENBQ3ZFLElBQUks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