Skip to content

Commit

Permalink
Fix heatmap layer performance regression
Browse files Browse the repository at this point in the history
  • Loading branch information
jfirebaugh committed Nov 16, 2017
1 parent fb3893e commit 51aace0
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 24 deletions.
26 changes: 5 additions & 21 deletions src/style/properties.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
const assert = require('assert');
const {extend, easeCubicInOut} = require('../util/util');
const interpolate = require('../style-spec/util/interpolate');
const {RGBAImage} = require('../util/image');
const {normalizePropertyExpression} = require('../style-spec/expression');
const Color = require('../style-spec/util/color');

Expand Down Expand Up @@ -616,35 +615,20 @@ class CrossFadedProperty<T> implements Property<T, ?CrossFaded<T>> {
}

/**
* An implementation of `Property` for `heatmap-color`, which has unique evaluation requirements.
* An implementation of `Property` for `heatmap-color`. Evaluation and interpolation are no-ops: the real
* evaluation happens in HeatmapStyleLayer.
*
* @private
*/
class HeatmapColorProperty implements Property<Color, RGBAImage> {
class HeatmapColorProperty implements Property<Color, void> {
specification: StylePropertySpecification;

constructor(specification: StylePropertySpecification) {
this.specification = specification;
}

possiblyEvaluate(value: PropertyValue<Color, RGBAImage>, parameters: EvaluationParameters): RGBAImage {
const colorRampData = new Uint8Array(256 * 4);
const len = colorRampData.length;
for (let i = 4; i < len; i += 4) {
const pxColor = value.expression.evaluate(extend({heatmapDensity: i / len}, parameters));
// the colors are being unpremultiplied because Color uses
// premultiplied values, and the Texture class expects unpremultiplied ones
colorRampData[i + 0] = Math.floor(pxColor.r * 255 / pxColor.a);
colorRampData[i + 1] = Math.floor(pxColor.g * 255 / pxColor.a);
colorRampData[i + 2] = Math.floor(pxColor.b * 255 / pxColor.a);
colorRampData[i + 3] = Math.floor(pxColor.a * 255);
}
return RGBAImage.create({width: 256, height: 1}, colorRampData);
}

interpolate(a: RGBAImage): RGBAImage {
return a;
}
possiblyEvaluate() {}
interpolate() {}
}

module.exports = {
Expand Down
27 changes: 24 additions & 3 deletions src/style/style_layer/heatmap_style_layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,32 @@ class HeatmapStyleLayer extends StyleLayer {

constructor(layer: LayerSpecification) {
super(layer, properties);

// make sure color ramp texture is generated for default heatmap color too
this._updateColorRamp();
}

updatePaintTransitions(options: {transition?: boolean}, transition: TransitionSpecification) {
super.updatePaintTransitions(options, transition);
this.colorRamp = this._transitioningPaint._values['heatmap-color'].possiblyEvaluate(({zoom: 0}: any));
setPaintProperty(name: string, value: mixed, options: {validate: boolean}) {
super.setPaintProperty(name, value, options);
if (name === 'heatmap-color') {
this._updateColorRamp();
}
}

_updateColorRamp() {
const expression = this._transitionablePaint._values['heatmap-color'].value.expression;
const colorRampData = new Uint8Array(256 * 4);
const len = colorRampData.length;
for (let i = 4; i < len; i += 4) {
const pxColor = expression.evaluate(({heatmapDensity: i / len}: any));
// the colors are being unpremultiplied because Color uses
// premultiplied values, and the Texture class expects unpremultiplied ones
colorRampData[i + 0] = Math.floor(pxColor.r * 255 / pxColor.a);
colorRampData[i + 1] = Math.floor(pxColor.g * 255 / pxColor.a);
colorRampData[i + 2] = Math.floor(pxColor.b * 255 / pxColor.a);
colorRampData[i + 3] = Math.floor(pxColor.a * 255);
}
this.colorRamp = RGBAImage.create({width: 256, height: 1}, colorRampData);
this.colorRampTexture = null;
}

Expand Down

0 comments on commit 51aace0

Please sign in to comment.