-
-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Speed up vector layer rendering, fix drawing
- Fix issues with drawing polygons, including drawing polygons over poles - Allow drawn polygons to have properties set like other layers (color, opacity, etc) - When drawing, draw both points and polygons - Add CustomDataSource support - Greatly reduce the number of re-renders Cesium must do (improve map performance) - Add connectors between GeoPoints collection and polygons & points Entities Issues #2180 and #2189
- Loading branch information
Showing
15 changed files
with
1,270 additions
and
960 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
"use strict"; | ||
|
||
/*global define */ | ||
define([ | ||
"backbone", | ||
"cesium", | ||
"collections/maps/GeoPoints", | ||
"models/maps/assets/CesiumVectorData", | ||
], function (Backbone, Cesium, GeoPoints, CesiumVectorData) { | ||
/** | ||
* @class GeoPointsCesiumConnector | ||
* @classdesc This is the base model for other connectors that create geometry | ||
* in Cesium based on points in a GeoPoints collection. | ||
* @name GeoPointsCesiumConnector | ||
* @extends Backbone.Model | ||
* @constructor | ||
* @classcategory Models/Connectors | ||
* @since x.x.x | ||
*/ | ||
return Backbone.Model.extend( | ||
/** @lends GeoPointsCesiumConnector.prototype */ { | ||
/** | ||
* The type of Backbone.Model this is. | ||
* @type {string} | ||
* @default "GeoPointsCesiumConnector" | ||
*/ | ||
type: "GeoPointsCesiumConnector", | ||
|
||
/** | ||
* Extends the default Backbone.Model.defaults() function to specify | ||
* default attributes for the GeoPointsCesiumConnector model. | ||
* @returns {Object} The default attributes | ||
* @property {GeoPoints} geoPoints - The points collection to visualize | ||
* @property {CesiumVectorData} layer - The CesiumVectorData model to use | ||
* to visualize the points. This must be a CesiumVectorData model. | ||
* @property {Boolean} isConnected - Whether the layer is currently being | ||
* updated with changes to the points collection. | ||
*/ | ||
defaults: function () { | ||
return { | ||
geoPoints: null, | ||
layer: null, | ||
isConnected: false, | ||
}; | ||
}, | ||
|
||
/** | ||
* Initialize the model. | ||
* @param {Object} attrs - The attributes for this model. | ||
* @param {GeoPoints | Array} [attributes.geoPoints] - The GeoPoints | ||
* collection to use for this connector or an array of JSON attributes to | ||
* create a new GeoPoints collection. If not provided, a new empty | ||
* GeoPoints collection will be created. | ||
* @param {CesiumVectorData | Object} [attributes.layer] - The | ||
* CesiumVectorData CesiumVectorData model to use for this connector or a | ||
* JSON object with options to create a model. If not provided, a new | ||
* layer will be created. | ||
*/ | ||
initialize: function (attrs) { | ||
try { | ||
attrs = attrs || {}; | ||
this.setGeoPoints(attrs.geoPoints); | ||
this.setLayer(attrs.layer); | ||
if (attrs.isConnected) { | ||
this.connect(); | ||
} | ||
} catch (e) { | ||
console.log("Error initializing a GeoPointsCesiumConnector", e); | ||
} | ||
}, | ||
|
||
/** | ||
* Set or create and set the GeoPoints collection for this connector. | ||
* @param {GeoPoints | Object} [points] - The GeoPoints collection to use | ||
* for this connector or an array of JSON attributes to create points. | ||
* @returns {GeoPoints} The GeoPoints collection for this connector. | ||
*/ | ||
setGeoPoints: function (geoPoints) { | ||
if (geoPoints instanceof GeoPoints) { | ||
this.set("geoPoints", geoPoints); | ||
} else { | ||
this.set("geoPoints", new GeoPoints(geoPoints)); | ||
} | ||
return this.get("geoPoints"); | ||
}, | ||
|
||
/** | ||
* Set or create and set the CesiumVectorData model for this connector. | ||
* @param {CesiumVectorData | Object} [layer] - The CesiumVectorData model | ||
* to use for this connector or a JSON object with options to create a new | ||
* CesiumVectorData model. If not provided, a new CesiumVectorData model | ||
* will be created. | ||
* @returns {CesiumVectorData} The CesiumVectorData model for this | ||
* connector. | ||
*/ | ||
setLayer: function (layer) { | ||
if (layer instanceof CesiumVectorData) { | ||
this.set("layer", layer); | ||
} else { | ||
this.set("layer", new CesiumVectorData(layer)); | ||
} | ||
return this.get("layer"); | ||
}, | ||
|
||
/** | ||
* Listen for changes to the Points collection and update the | ||
* CesiumVectorData model with point entities. | ||
*/ | ||
connect: function () { | ||
try { | ||
// Listen for changes to the points collection and update the layer | ||
let geoPoints = this.get("geoPoints"); | ||
const events = ["update", "reset"]; | ||
events.forEach((eventName) => { | ||
this.listenTo(geoPoints, eventName, function (...args) { | ||
this.handleCollectionChange(eventName, ...args); | ||
}); | ||
}); | ||
|
||
// Restart listeners when points or the layer is replaced | ||
this.listenToOnce(this, "change:geoPoints change:layer", () => { | ||
if (this.get("isConnected")) { | ||
this.connect(); | ||
} | ||
}); | ||
// Restart listeners when points or the layer is replaced | ||
this.listenToOnce(this, "change:geoPoints change:layer", () => { | ||
if (this.get("isConnected")) { | ||
this.connect(); | ||
} | ||
}); | ||
|
||
this.set("isConnected", true); | ||
} catch (e) { | ||
console.warn("Error connecting Points to Cesium. Disconnecting.", e); | ||
this.disconnect(); | ||
} | ||
}, | ||
|
||
/** | ||
* Stop listening for changes to the Points collection. | ||
*/ | ||
disconnect: function () { | ||
this.stopListening(this.get("geoPoints")); | ||
this.set("isConnected", false); | ||
}, | ||
|
||
/** | ||
* Handle add, remove, merge, and reset events from the points collection | ||
* @param {"update"|"reset"} eventName - The name of the event | ||
* @param {GeoPoints} collection - The points collection | ||
* @param {Object} options - Options for the event, as passed by Backbone | ||
*/ | ||
handleCollectionChange(eventName, collection, options) { | ||
try { | ||
// What to do when the collection changes | ||
} catch (e) { | ||
console.warn('Error handling a "' + eventName + '" event.', e); | ||
} | ||
}, | ||
} | ||
); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
"use strict"; | ||
|
||
/*global define */ | ||
define(["cesium", "models/connectors/GeoPoints-Cesium"], function ( | ||
Cesium, | ||
GeoPointsCesiumConnector | ||
) { | ||
/** | ||
* @class GeoPointsCesiumPointsConnector | ||
* @classdesc This connector keeps a CesiumVectorData model in sync with the | ||
* points in a GeoPoints collection. This connector will listen for changes to | ||
* the GeoPoints collection and update the cesiumModel with point entities | ||
* created from the points in the collection. | ||
* @name GeoPointsCesiumPointsConnector | ||
* @extends GeoPointsCesiumConnector | ||
* @constructor | ||
* @classcategory Models/Connectors | ||
* @since x.x.x | ||
*/ | ||
return GeoPointsCesiumConnector.extend( | ||
/** @lends GeoPointsCesiumPointsConnector.prototype */ { | ||
/** | ||
* The type of Backbone.Model this is. | ||
* @type {string} | ||
* @default "GeoPointsCesiumPointsConnector" | ||
*/ | ||
type: "GeoPointsCesiumPointsConnector", | ||
|
||
/** | ||
* Extends the default Backbone.Model.defaults() function to specify | ||
* default attributes for the GeoPointsCesiumPointsConnector model. | ||
* @extends GeoPointsCesiumConnector.defaults | ||
* @returns {Object} The default attributes | ||
* @property {Array} layerPoints - The list of point entities that have | ||
* been added to the layer. | ||
*/ | ||
defaults: function () { | ||
return { | ||
// extend the defaults from the parent class | ||
...GeoPointsCesiumConnector.prototype.defaults(), | ||
layerPoints: [], | ||
}; | ||
}, | ||
|
||
/** | ||
* Handle add, remove, merge, and reset events from the points collection | ||
* @param {"update"|"reset"} eventName - The name of the event | ||
* @param {GeoPoints} collection - The points collection | ||
* @param {Object} options - Options for the event, as passed by Backbone | ||
*/ | ||
handleCollectionChange(eventName, collection, options) { | ||
try { | ||
// For merges and resets, just remove all points and re-add them | ||
if (!options?.add && !options?.remove) { | ||
this.resetLayerPoints(); | ||
return; | ||
} | ||
// For adds and removes, just add or remove the points that changed | ||
if (eventName === "update") { | ||
if (options.add) { | ||
const newModels = options.changes.added; | ||
newModels.forEach((model) => { | ||
this.addLayerPoint(model); | ||
}); | ||
} | ||
if (options.remove) { | ||
const removedModels = options.changes.removed; | ||
removedModels.forEach((model) => { | ||
this.removeLayerPoint(model); | ||
}); | ||
} | ||
} | ||
} catch (e) { | ||
console.warn('Error handling a "' + eventName + '" event.', e); | ||
} | ||
}, | ||
|
||
/** | ||
* Resync the layer points with the points from the points collection. | ||
* This removes all point entities previously added to the layer and adds | ||
* new ones for each point in the points collection. | ||
*/ | ||
resetLayerPoints: function () { | ||
const layer = this.get("layer"); | ||
layer.suspendEvents(); | ||
this.removeAllLayerPoints(); | ||
this.addAllLayerPoints(); | ||
layer.resumeEvents(); | ||
}, | ||
|
||
/** | ||
* Remove all layer points previously added to the layer. | ||
* @returns {Boolean} Whether the layer points were removed | ||
*/ | ||
removeAllLayerPoints: function () { | ||
const layer = this.get("layer"); | ||
if (!layer) return false; | ||
const layerPoints = this.get("layerPoints"); | ||
layerPoints.forEach((entity) => { | ||
layer.removeEntity(entity); | ||
}); | ||
return true; | ||
}, | ||
|
||
/** | ||
* Add all points from the points collection to the layer. | ||
* @returns {Boolean} Whether the layer points were added | ||
*/ | ||
addAllLayerPoints: function () { | ||
const layer = this.get("layer"); | ||
if (!layer) return false; | ||
const geoPoints = this.get("geoPoints"); | ||
geoPoints.each((model) => { | ||
this.addLayerPoint(model); | ||
}); | ||
return true; | ||
}, | ||
|
||
/** | ||
* Add a point from the points collection to the layer. Adds the point | ||
* entity to the layerPoints array for tracking. | ||
* @param {GeoPoint} model - The point model to add to the layer | ||
* @returns {Cesium.Entity} The layer point that was created | ||
*/ | ||
addLayerPoint: function (model) { | ||
try { | ||
const layer = this.get("layer") || this.setLayer(); | ||
const layerPoint = layer.addEntity({ | ||
id: model.cid, | ||
position: model.get("mapWidgetCoords"), | ||
point: { | ||
pixelSize: 2, | ||
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, | ||
}, | ||
}); | ||
// Track the layer point so we can remove it later | ||
const layerPoints = this.get("layerPoints"); | ||
layerPoints.push(layerPoint); | ||
return layerPoint; | ||
} catch (e) { | ||
console.log("Failed to add a point to a CesiumVectorData.", e); | ||
} | ||
}, | ||
|
||
/** | ||
* Remove a point from the points collection from the layer. Removes the | ||
* point entity from the layerPoints array. | ||
* @param {GeoPoint} model - The point model to remove from the layer | ||
* @returns {Cesium.Entity} The layer point that was removed | ||
*/ | ||
removeLayerPoint: function (model) { | ||
try { | ||
const layer = this.get("layer"); | ||
if (!layer) return false; | ||
const removedPoint = layer.removeEntity(model.cid); | ||
// Remove the layer point from the list of layer points | ||
const layerPoints = this.get("layerPoints"); | ||
const index = layerPoints.indexOf(removedPoint); | ||
if (index > -1) { | ||
layerPoints.splice(index, 1); | ||
} | ||
return removedPoint; | ||
} catch (e) { | ||
console.log("Failed to remove a point from a CesiumVectorData.", e); | ||
} | ||
}, | ||
} | ||
); | ||
}); |
Oops, something went wrong.