123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510 |
- import ApproximateTerrainHeights from "../Core/ApproximateTerrainHeights.js";
- import BoundingSphere from "../Core/BoundingSphere.js";
- import Check from "../Core/Check.js";
- import defaultValue from "../Core/defaultValue.js";
- import defined from "../Core/defined.js";
- import destroyObject from "../Core/destroyObject.js";
- import EventHelper from "../Core/EventHelper.js";
- import GroundPolylinePrimitive from "../Scene/GroundPolylinePrimitive.js";
- import GroundPrimitive from "../Scene/GroundPrimitive.js";
- import OrderedGroundPrimitiveCollection from "../Scene/OrderedGroundPrimitiveCollection.js";
- import PrimitiveCollection from "../Scene/PrimitiveCollection.js";
- import BillboardVisualizer from "./BillboardVisualizer.js";
- import BoundingSphereState from "./BoundingSphereState.js";
- import CustomDataSource from "./CustomDataSource.js";
- import GeometryVisualizer from "./GeometryVisualizer.js";
- import LabelVisualizer from "./LabelVisualizer.js";
- import ModelVisualizer from "./ModelVisualizer.js";
- import Cesium3DTilesetVisualizer from "./Cesium3DTilesetVisualizer.js";
- import PathVisualizer from "./PathVisualizer.js";
- import PointVisualizer from "./PointVisualizer.js";
- import PolylineVisualizer from "./PolylineVisualizer.js";
- /**
- * Visualizes a collection of {@link DataSource} instances.
- * @alias DataSourceDisplay
- * @constructor
- *
- * @param {Object} options Object with the following properties:
- * @param {Scene} options.scene The scene in which to display the data.
- * @param {DataSourceCollection} options.dataSourceCollection The data sources to display.
- * @param {DataSourceDisplay.VisualizersCallback} [options.visualizersCallback=DataSourceDisplay.defaultVisualizersCallback]
- * A function which creates an array of visualizers used for visualization.
- * If undefined, all standard visualizers are used.
- */
- function DataSourceDisplay(options) {
- //>>includeStart('debug', pragmas.debug);
- Check.typeOf.object("options", options);
- Check.typeOf.object("options.scene", options.scene);
- Check.typeOf.object(
- "options.dataSourceCollection",
- options.dataSourceCollection
- );
- //>>includeEnd('debug');
- GroundPrimitive.initializeTerrainHeights();
- GroundPolylinePrimitive.initializeTerrainHeights();
- const scene = options.scene;
- const dataSourceCollection = options.dataSourceCollection;
- this._eventHelper = new EventHelper();
- this._eventHelper.add(
- dataSourceCollection.dataSourceAdded,
- this._onDataSourceAdded,
- this
- );
- this._eventHelper.add(
- dataSourceCollection.dataSourceRemoved,
- this._onDataSourceRemoved,
- this
- );
- this._eventHelper.add(
- dataSourceCollection.dataSourceMoved,
- this._onDataSourceMoved,
- this
- );
- this._eventHelper.add(scene.postRender, this._postRender, this);
- this._dataSourceCollection = dataSourceCollection;
- this._scene = scene;
- this._visualizersCallback = defaultValue(
- options.visualizersCallback,
- DataSourceDisplay.defaultVisualizersCallback
- );
- let primitivesAdded = false;
- const primitives = new PrimitiveCollection();
- const groundPrimitives = new PrimitiveCollection();
- if (dataSourceCollection.length > 0) {
- scene.primitives.add(primitives);
- scene.groundPrimitives.add(groundPrimitives);
- primitivesAdded = true;
- }
- this._primitives = primitives;
- this._groundPrimitives = groundPrimitives;
- for (let i = 0, len = dataSourceCollection.length; i < len; i++) {
- this._onDataSourceAdded(dataSourceCollection, dataSourceCollection.get(i));
- }
- const defaultDataSource = new CustomDataSource();
- this._onDataSourceAdded(undefined, defaultDataSource);
- this._defaultDataSource = defaultDataSource;
- let removeDefaultDataSourceListener;
- let removeDataSourceCollectionListener;
- if (!primitivesAdded) {
- const that = this;
- const addPrimitives = function () {
- scene.primitives.add(primitives);
- scene.groundPrimitives.add(groundPrimitives);
- removeDefaultDataSourceListener();
- removeDataSourceCollectionListener();
- that._removeDefaultDataSourceListener = undefined;
- that._removeDataSourceCollectionListener = undefined;
- };
- removeDefaultDataSourceListener = defaultDataSource.entities.collectionChanged.addEventListener(
- addPrimitives
- );
- removeDataSourceCollectionListener = dataSourceCollection.dataSourceAdded.addEventListener(
- addPrimitives
- );
- }
- this._removeDefaultDataSourceListener = removeDefaultDataSourceListener;
- this._removeDataSourceCollectionListener = removeDataSourceCollectionListener;
- this._ready = false;
- }
- /**
- * Gets or sets the default function which creates an array of visualizers used for visualization.
- * By default, this function uses all standard visualizers.
- *
- * @type {DataSourceDisplay.VisualizersCallback}
- */
- DataSourceDisplay.defaultVisualizersCallback = function (
- scene,
- entityCluster,
- dataSource
- ) {
- const entities = dataSource.entities;
- return [
- new BillboardVisualizer(entityCluster, entities),
- new GeometryVisualizer(
- scene,
- entities,
- dataSource._primitives,
- dataSource._groundPrimitives
- ),
- new LabelVisualizer(entityCluster, entities),
- new ModelVisualizer(scene, entities),
- new Cesium3DTilesetVisualizer(scene, entities),
- new PointVisualizer(entityCluster, entities),
- new PathVisualizer(scene, entities),
- new PolylineVisualizer(
- scene,
- entities,
- dataSource._primitives,
- dataSource._groundPrimitives
- ),
- ];
- };
- Object.defineProperties(DataSourceDisplay.prototype, {
- /**
- * Gets the scene associated with this display.
- * @memberof DataSourceDisplay.prototype
- * @type {Scene}
- */
- scene: {
- get: function () {
- return this._scene;
- },
- },
- /**
- * Gets the collection of data sources to display.
- * @memberof DataSourceDisplay.prototype
- * @type {DataSourceCollection}
- */
- dataSources: {
- get: function () {
- return this._dataSourceCollection;
- },
- },
- /**
- * 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.
- * @memberof DataSourceDisplay.prototype
- * @type {CustomDataSource}
- */
- defaultDataSource: {
- get: function () {
- return this._defaultDataSource;
- },
- },
- /**
- * Gets a value indicating whether or not all entities in the data source are ready
- * @memberof DataSourceDisplay.prototype
- * @type {Boolean}
- * @readonly
- */
- ready: {
- get: function () {
- return this._ready;
- },
- },
- });
- /**
- * Returns true if this object was destroyed; otherwise, false.
- * <br /><br />
- * If this object was destroyed, it should not be used; calling any function other than
- * <code>isDestroyed</code> will result in a {@link DeveloperError} exception.
- *
- * @returns {Boolean} True if this object was destroyed; otherwise, false.
- *
- * @see DataSourceDisplay#destroy
- */
- DataSourceDisplay.prototype.isDestroyed = function () {
- return false;
- };
- /**
- * Destroys the WebGL resources held by this object. Destroying an object allows for deterministic
- * release of WebGL resources, instead of relying on the garbage collector to destroy this object.
- * <br /><br />
- * Once an object is destroyed, it should not be used; calling any function other than
- * <code>isDestroyed</code> will result in a {@link DeveloperError} exception. Therefore,
- * assign the return value (<code>undefined</code>) to the object as done in the example.
- *
- * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.
- *
- *
- * @example
- * dataSourceDisplay = dataSourceDisplay.destroy();
- *
- * @see DataSourceDisplay#isDestroyed
- */
- DataSourceDisplay.prototype.destroy = function () {
- 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);
- if (defined(this._removeDefaultDataSourceListener)) {
- this._removeDefaultDataSourceListener();
- this._removeDataSourceCollectionListener();
- } else {
- this._scene.primitives.remove(this._primitives);
- this._scene.groundPrimitives.remove(this._groundPrimitives);
- }
- return destroyObject(this);
- };
- /**
- * Updates the display to the provided time.
- *
- * @param {JulianDate} time The simulation time.
- * @returns {Boolean} True if all data sources are ready to be displayed, false otherwise.
- */
- DataSourceDisplay.prototype.update = function (time) {
- //>>includeStart('debug', pragmas.debug);
- Check.defined("time", time);
- //>>includeEnd('debug');
- if (!ApproximateTerrainHeights.initialized) {
- this._ready = false;
- return false;
- }
- let result = true;
- let i;
- let x;
- let visualizers;
- let vLength;
- const dataSources = this._dataSourceCollection;
- const length = dataSources.length;
- for (i = 0; i < length; i++) {
- const dataSource = dataSources.get(i);
- if (defined(dataSource.update)) {
- result = dataSource.update(time) && result;
- }
- visualizers = dataSource._visualizers;
- vLength = visualizers.length;
- for (x = 0; x < vLength; x++) {
- result = visualizers[x].update(time) && result;
- }
- }
- visualizers = this._defaultDataSource._visualizers;
- vLength = visualizers.length;
- for (x = 0; x < vLength; x++) {
- result = visualizers[x].update(time) && result;
- }
- this._ready = result;
- return result;
- };
- DataSourceDisplay.prototype._postRender = function () {
- // Adds credits for all datasources
- const frameState = this._scene.frameState;
- const dataSources = this._dataSourceCollection;
- const length = dataSources.length;
- for (let i = 0; i < length; i++) {
- const dataSource = dataSources.get(i);
- const credit = dataSource.credit;
- if (defined(credit)) {
- frameState.creditDisplay.addCredit(credit);
- }
- // Credits from the resource that the user can't remove
- const credits = dataSource._resourceCredits;
- if (defined(credits)) {
- const creditCount = credits.length;
- for (let c = 0; c < creditCount; c++) {
- frameState.creditDisplay.addCredit(credits[c]);
- }
- }
- }
- };
- const getBoundingSphereArrayScratch = [];
- const getBoundingSphereBoundingSphereScratch = new BoundingSphere();
- /**
- * 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.
- *
- * @param {Entity} entity The entity whose bounding sphere to compute.
- * @param {Boolean} allowPartial If true, pending bounding spheres are ignored and an answer will be returned from the currently available data.
- * If false, the the function will halt and return pending if any of the bounding spheres are pending.
- * @param {BoundingSphere} result The bounding sphere onto which to store the result.
- * @returns {BoundingSphereState} BoundingSphereState.DONE if the result contains the bounding sphere,
- * BoundingSphereState.PENDING if the result is still being computed, or
- * BoundingSphereState.FAILED if the entity has no visualization in the current scene.
- * @private
- */
- DataSourceDisplay.prototype.getBoundingSphere = function (
- entity,
- allowPartial,
- result
- ) {
- //>>includeStart('debug', pragmas.debug);
- Check.defined("entity", entity);
- Check.typeOf.bool("allowPartial", allowPartial);
- Check.defined("result", result);
- //>>includeEnd('debug');
- if (!this._ready) {
- return BoundingSphereState.PENDING;
- }
- let i;
- let length;
- let dataSource = this._defaultDataSource;
- if (!dataSource.entities.contains(entity)) {
- dataSource = undefined;
- const dataSources = this._dataSourceCollection;
- length = dataSources.length;
- for (i = 0; i < length; i++) {
- const d = dataSources.get(i);
- if (d.entities.contains(entity)) {
- dataSource = d;
- break;
- }
- }
- }
- if (!defined(dataSource)) {
- return BoundingSphereState.FAILED;
- }
- const boundingSpheres = getBoundingSphereArrayScratch;
- const tmp = getBoundingSphereBoundingSphereScratch;
- let count = 0;
- let state = BoundingSphereState.DONE;
- const visualizers = dataSource._visualizers;
- const visualizersLength = visualizers.length;
- for (i = 0; i < visualizersLength; i++) {
- const visualizer = visualizers[i];
- if (defined(visualizer.getBoundingSphere)) {
- state = visualizers[i].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;
- };
- DataSourceDisplay.prototype._onDataSourceAdded = function (
- dataSourceCollection,
- dataSource
- ) {
- const scene = this._scene;
- const displayPrimitives = this._primitives;
- const displayGroundPrimitives = this._groundPrimitives;
- const primitives = displayPrimitives.add(new PrimitiveCollection());
- const groundPrimitives = displayGroundPrimitives.add(
- new OrderedGroundPrimitiveCollection()
- );
- dataSource._primitives = primitives;
- dataSource._groundPrimitives = groundPrimitives;
- const entityCluster = dataSource.clustering;
- entityCluster._initialize(scene);
- primitives.add(entityCluster);
- dataSource._visualizers = this._visualizersCallback(
- scene,
- entityCluster,
- dataSource
- );
- };
- DataSourceDisplay.prototype._onDataSourceRemoved = function (
- dataSourceCollection,
- dataSource
- ) {
- const displayPrimitives = this._primitives;
- const displayGroundPrimitives = this._groundPrimitives;
- const primitives = dataSource._primitives;
- const groundPrimitives = dataSource._groundPrimitives;
- const entityCluster = dataSource.clustering;
- primitives.remove(entityCluster);
- const visualizers = dataSource._visualizers;
- const length = visualizers.length;
- for (let i = 0; i < length; i++) {
- visualizers[i].destroy();
- }
- displayPrimitives.remove(primitives);
- displayGroundPrimitives.remove(groundPrimitives);
- dataSource._visualizers = undefined;
- };
- DataSourceDisplay.prototype._onDataSourceMoved = function (
- dataSource,
- newIndex,
- oldIndex
- ) {
- const displayPrimitives = this._primitives;
- const displayGroundPrimitives = this._groundPrimitives;
- const primitives = dataSource._primitives;
- const groundPrimitives = dataSource._groundPrimitives;
- if (newIndex === oldIndex + 1) {
- displayPrimitives.raise(primitives);
- displayGroundPrimitives.raise(groundPrimitives);
- } else if (newIndex === oldIndex - 1) {
- displayPrimitives.lower(primitives);
- displayGroundPrimitives.lower(groundPrimitives);
- } else if (newIndex === 0) {
- displayPrimitives.lowerToBottom(primitives);
- displayGroundPrimitives.lowerToBottom(groundPrimitives);
- displayPrimitives.raise(primitives); // keep defaultDataSource primitives at index 0 since it's not in the collection
- displayGroundPrimitives.raise(groundPrimitives);
- } else {
- displayPrimitives.raiseToTop(primitives);
- displayGroundPrimitives.raiseToTop(groundPrimitives);
- }
- };
- /**
- * A function which creates an array of visualizers used for visualization.
- * @callback DataSourceDisplay.VisualizersCallback
- *
- * @param {Scene} scene The scene to create visualizers for.
- * @param {DataSource} dataSource The data source to create visualizers for.
- * @returns {Visualizer[]} An array of visualizers used for visualization.
- *
- * @example
- * function createVisualizers(scene, dataSource) {
- * return [new Cesium.BillboardVisualizer(scene, dataSource.entities)];
- * }
- */
- export default DataSourceDisplay;
|