cesium
Version:
CesiumJS is a JavaScript library for creating 3D globes and 2D maps in a web browser without a plugin.
142 lines (126 loc) • 6.72 kB
JavaScript
import Color from '../Core/Color.js';
import defined from '../Core/defined.js';
import JulianDate from '../Core/JulianDate.js';
import CesiumMath from '../Core/Math.js';
/**
* A heatmap colorizer in a {@link Cesium3DTileset}. A tileset can colorize its visible tiles in a heatmap style.
*
* @alias Cesium3DTilesetHeatmap
* @constructor
* @private
*/
function Cesium3DTilesetHeatmap(tilePropertyName) {
/**
* The tile variable to track for heatmap colorization.
* Tile's will be colorized relative to the other visible tile's values for this variable.
*
* @type {String}
*/
this.tilePropertyName = tilePropertyName;
// Members that are updated every time a tile is colorized
this._minimum = Number.MAX_VALUE;
this._maximum = -Number.MAX_VALUE;
// Members that are updated once every frame
this._previousMinimum = Number.MAX_VALUE;
this._previousMaximum = -Number.MAX_VALUE;
// If defined uses a reference minimum maximum to colorize by instead of using last frames minimum maximum of rendered tiles.
// For example, the _loadTimestamp can get a better colorization using setReferenceMinimumMaximum in order to take accurate colored timing diffs of various scenes.
this._referenceMinimum = {};
this._referenceMaximum = {};
}
/**
* Convert to a usable heatmap value (i.e. a number). Ensures that tile values that aren't stored as numbers can be used for colorization.
*/
function getHeatmapValue(tileValue, tilePropertyName) {
var value;
if (tilePropertyName === '_loadTimestamp') {
value = JulianDate.toDate(tileValue).getTime();
} else {
value = tileValue;
}
return value;
}
/**
* Sets the reference minimum and maximum for the variable name. Converted to numbers before they are stored.
*
* @param {Object} minimum The minimum reference value.
* @param {Object} maximum The maximum reference value.
* @param {String} tilePropertyName The tile variable that will use these reference values when it is colorized.
*/
Cesium3DTilesetHeatmap.prototype.setReferenceMinimumMaximum = function(minimum, maximum, tilePropertyName) {
this._referenceMinimum[tilePropertyName] = getHeatmapValue(minimum, tilePropertyName);
this._referenceMaximum[tilePropertyName] = getHeatmapValue(maximum, tilePropertyName);
};
function getHeatmapValueAndUpdateMinimumMaximum(heatmap, tile) {
var tilePropertyName = heatmap.tilePropertyName;
if (defined(tilePropertyName)) {
var heatmapValue = getHeatmapValue(tile[tilePropertyName], tilePropertyName);
if (!defined(heatmapValue)) {
heatmap.tilePropertyName = undefined;
return heatmapValue;
}
heatmap._maximum = Math.max(heatmapValue, heatmap._maximum);
heatmap._minimum = Math.min(heatmapValue, heatmap._minimum);
return heatmapValue;
}
}
var heatmapColors = [new Color(0.100, 0.100, 0.100, 1), // Dark Gray
new Color(0.153, 0.278, 0.878, 1), // Blue
new Color(0.827, 0.231, 0.490, 1), // Pink
new Color(0.827, 0.188, 0.220, 1), // Red
new Color(1.000, 0.592, 0.259, 1), // Orange
new Color(1.000, 0.843, 0.000, 1)]; // Yellow
/**
* Colorize the tile in heat map style based on where it lies within the minimum maximum window.
* Heatmap colors are black, blue, pink, red, orange, yellow. 'Cold' or low numbers will be black and blue, 'Hot' or high numbers will be orange and yellow,
* @param {Cesium3DTile} tile The tile to colorize relative to last frame's minimum and maximum values of all visible tiles.
* @param {FrameState} frameState The frame state.
*/
Cesium3DTilesetHeatmap.prototype.colorize = function (tile, frameState) {
var tilePropertyName = this.tilePropertyName;
if (!defined(tilePropertyName) || !tile.contentAvailable || tile._selectedFrame !== frameState.frameNumber) {
return;
}
var heatmapValue = getHeatmapValueAndUpdateMinimumMaximum(this, tile);
var minimum = this._previousMinimum;
var maximum = this._previousMaximum;
if (minimum === Number.MAX_VALUE || maximum === -Number.MAX_VALUE) {
return;
}
// Shift the minimum maximum window down to 0
var shiftedMax = (maximum - minimum) + CesiumMath.EPSILON7; // Prevent divide by 0
var shiftedValue = CesiumMath.clamp(heatmapValue - minimum, 0.0, shiftedMax);
// Get position between minimum and maximum and convert that to a position in the color array
var zeroToOne = shiftedValue / shiftedMax;
var lastIndex = heatmapColors.length - 1.0;
var colorPosition = zeroToOne * lastIndex;
// Take floor and ceil of the value to get the two colors to lerp between, lerp using the fractional portion
var colorPositionFloor = Math.floor(colorPosition);
var colorPositionCeil = Math.ceil(colorPosition);
var t = colorPosition - colorPositionFloor;
var colorZero = heatmapColors[colorPositionFloor];
var colorOne = heatmapColors[colorPositionCeil];
// Perform the lerp
var finalColor = Color.clone(Color.WHITE);
finalColor.red = CesiumMath.lerp(colorZero.red, colorOne.red, t);
finalColor.green = CesiumMath.lerp(colorZero.green, colorOne.green, t);
finalColor.blue = CesiumMath.lerp(colorZero.blue, colorOne.blue, t);
tile._debugColor = finalColor;
};
/**
* Resets the tracked minimum maximum values for heatmap colorization. Happens right before tileset traversal.
*/
Cesium3DTilesetHeatmap.prototype.resetMinimumMaximum = function() {
// For heat map colorization
var tilePropertyName = this.tilePropertyName;
if (defined(tilePropertyName)) {
var referenceMinimum = this._referenceMinimum[tilePropertyName];
var referenceMaximum = this._referenceMaximum[tilePropertyName];
var useReference = defined(referenceMinimum) && defined(referenceMaximum);
this._previousMinimum = useReference ? referenceMinimum : this._minimum;
this._previousMaximum = useReference ? referenceMaximum : this._maximum;
this._minimum = Number.MAX_VALUE;
this._maximum = -Number.MAX_VALUE;
}
};
export default Cesium3DTilesetHeatmap;