UNPKG

terriajs

Version:

Geospatial data visualization platform.

215 lines 8.93 kB
import L from "leaflet"; import BoundingSphere from "terriajs-cesium/Source/Core/BoundingSphere"; import EventHelper from "terriajs-cesium/Source/Core/EventHelper"; import JulianDate from "terriajs-cesium/Source/Core/JulianDate"; import createGuid from "terriajs-cesium/Source/Core/createGuid"; import destroyObject from "terriajs-cesium/Source/Core/destroyObject"; import BoundingSphereState from "terriajs-cesium/Source/DataSources/BoundingSphereState"; import CustomDataSource from "terriajs-cesium/Source/DataSources/CustomDataSource"; import DataSource from "terriajs-cesium/Source/DataSources/DataSource"; import isDefined from "../../Core/isDefined"; class LeafletDataSource extends DataSource { visualizersByDisplayID; visualizers; } /** * Visualizes a collection of {@link DataSource} instances in Leaflet. */ export default class LeafletDataSourceDisplay { _displayID; // Gets the scene associated with this display. _scene; /** * Gets the default data source instance which can be used to * manually create and visualize entities not tied to * a specific data source. This instance is always available * and does not appear in the list dataSources collection. */ _defaultDataSource; // Gets the collection of data sources to display. _dataSourceCollection; _visualizersCallback; _eventHelper; // Gets a value indicating whether or not all entities in the data source are ready _ready; _lastTime; constructor(options) { this._displayID = createGuid(); this._scene = options.scene; this._dataSourceCollection = options.dataSourceCollection; this._visualizersCallback = options.visualizersCallback ?? LeafletDataSourceDisplay.defaultVisualizersCallback; this._eventHelper = new EventHelper(); this._eventHelper.add(this._dataSourceCollection.dataSourceAdded, this._onDataSourceAdded, this); this._eventHelper.add(this._dataSourceCollection.dataSourceRemoved, this._onDataSourceRemoved, this); for (let i = 0, len = this._dataSourceCollection.length; i < len; i++) { this._onDataSourceAdded(this._dataSourceCollection, this._dataSourceCollection.get(i)); } const defaultDataSource = new CustomDataSource(); this._onDataSourceAdded(undefined, defaultDataSource); this._defaultDataSource = defaultDataSource; this._ready = false; this._lastTime = JulianDate.now(); } /** * Gets or sets the default function which creates an array of visualizers used for visualization. * By default, this function uses all standard visualizers. * */ static defaultVisualizersCallback(_leafletScene, _entityCluster, _dataSource) { return []; } /** * Updates the display to the provided time. * */ update(time) { let result = true; let x; let visualizers; let vLength; const dataSources = this._dataSourceCollection; const length = dataSources.length; for (let i = 0; i < length; i++) { const dataSource = dataSources.get(i); if (isDefined(dataSource.update)) { result = dataSource.update(time) && result; } visualizers = this._getVisualizersForDataSource(dataSource); if (isDefined(visualizers)) { vLength = visualizers.length; for (x = 0; x < vLength; x++) { result = visualizers[x].update(time) && result; } } } visualizers = this._getVisualizersForDataSource(this._defaultDataSource); if (isDefined(visualizers)) { vLength = visualizers.length; for (x = 0; x < vLength; x++) { result = visualizers[x].update(time) && result; } } this._ready = result; this._lastTime = JulianDate.clone(time, this._lastTime); return result; } destroy() { this._eventHelper.removeAll(); const dataSourceCollection = this._dataSourceCollection; for (let i = 0, length = dataSourceCollection.length; i < length; ++i) { this._onDataSourceRemoved(this._dataSourceCollection, dataSourceCollection.get(i)); } this._onDataSourceRemoved(undefined, this._defaultDataSource); return destroyObject(this); } _onDataSourceAdded(_dataSourceCollection, dataSource) { const visualizers = this._visualizersCallback(this._scene, undefined, dataSource); dataSource.visualizersByDisplayID = dataSource.visualizersByDisplayID || {}; dataSource.visualizersByDisplayID[this._displayID] = visualizers; dataSource.visualizers = dataSource.visualizers || []; dataSource.visualizers = dataSource.visualizers.concat(visualizers); } _onDataSourceRemoved(_dataSourceCollection, dataSource) { const visualizers = this._getVisualizersForDataSource(dataSource); if (!isDefined(visualizers)) { return; } const length = visualizers.length; for (let i = 0; i < length; i++) { const visualizer = visualizers[i]; visualizer.destroy(); if (isDefined(dataSource.visualizers)) { const index = dataSource.visualizers.indexOf(visualizer); dataSource.visualizers.splice(index, 1); } } if (isDefined(dataSource.visualizersByDisplayID)) { delete dataSource.visualizersByDisplayID[this._displayID]; } } _getVisualizersForDataSource(dataSource) { const visualizersByDisplayID = dataSource.visualizersByDisplayID; if (isDefined(visualizersByDisplayID) && isDefined(visualizersByDisplayID[this._displayID])) { return visualizersByDisplayID[this._displayID]; } } /** * Computes the rectangular bounds which encloses the visualization * produced for the given entities. */ getLatLngBounds(dataSource) { this.update(this._lastTime); const visualizers = this._getVisualizersForDataSource(dataSource); if (!isDefined(visualizers)) { return; } let result; for (let j = 0, vLength = visualizers.length; j < vLength; j++) { const visualizer = visualizers[j]; const bounds = visualizer.getLatLngBounds(); if (bounds === undefined) { continue; } result = result === undefined ? L.latLngBounds(bounds.getSouthWest(), bounds.getNorthEast()) : result.extend(bounds); } return result; } /** * Computes a bounding sphere which encloses the visualization produced for the specified entity. * The bounding sphere is in the fixed frame of the scene's globe. */ getBoundingSphere(entity, allowPartial, result) { if (!this._ready) { return BoundingSphereState.PENDING; } let length; let dataSource = this._defaultDataSource; if (!dataSource.entities.contains(entity)) { dataSource = undefined; const dataSources = this._dataSourceCollection; length = dataSources.length; for (let i = 0; i < length; i++) { const d = dataSources.get(i); if (d.entities.contains(entity)) { dataSource = d; break; } } } if (!isDefined(dataSource) || !isDefined(dataSource.visualizers)) { return BoundingSphereState.FAILED; } const boundingSpheres = []; const tmp = new BoundingSphere(); let count = 0; let state = BoundingSphereState.DONE; const visualizers = dataSource.visualizers; const visualizersLength = visualizers.length; for (let i = 0; i < visualizersLength; i++) { const visualizer = visualizers[i]; if (isDefined(visualizer.getBoundingSphere)) { state = visualizer.getBoundingSphere(entity, tmp); if (!allowPartial && state === BoundingSphereState.PENDING) { return BoundingSphereState.PENDING; } else if (state === BoundingSphereState.DONE) { boundingSpheres[count] = BoundingSphere.clone(tmp, boundingSpheres[count]); count++; } } } if (count === 0) { return BoundingSphereState.FAILED; } boundingSpheres.length = count; BoundingSphere.fromBoundingSpheres(boundingSpheres, result); return BoundingSphereState.DONE; } } //# sourceMappingURL=LeafletDataSourceDisplay.js.map