Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CARTO: Implement QuadbinHeatmapTileLayer #8703

Merged
merged 35 commits into from
Apr 29, 2024
Merged

Conversation

felixpalmer
Copy link
Collaborator

@felixpalmer felixpalmer commented Mar 25, 2024

Background

Implementation of custom layer for CARTO module to allow display of a QuadbinTileLayer as a heatmap. LIVE DEMO

Some of the ideas used here might be interesting for discussion for inclusion in core, however this PR aims to implement the functionality with minimal changes required to code outside of deck.gl/carto. As such, there may be a cleaner way if we move some of the code to core (see PostProcessModifier & OffscreenModifier below).

Screen.Recording.2024-03-25.at.14.47.44.mov

Implementation

Unlike the existing HeatmapLayer which renders points as 2D gaussians (essentially a blurred point) and then sums them, this layer performs the sum using a spatial index, and performs the blur in screen space. Both layers then apply a color map to the resulting value to give the familiar heatmap look.

Offscreen rendering

In order to achieve the above effect it was necessary to apply a custom post process effect to a single layer, specifically a CompositeLayer, to allow the use of tiled data.

A new set of helper functions is introduced to make it simpler to apply the postprocessing:

PostProcessModifier & OffscreenModifier

PostProcessModifer modifies a layer to make it apply a given post process effect:

const BlurredQuadbinTileLayer = PostProcessModifier(QuadbinTileLayer, triangleBlur);

For this to work, the non-composite layers that the CompositeLayer will draw will need to be rendered off-screen:

const OffscreenSolidPolygonLayer = OffscreenModifier(SolidPolygonLayer)
const _subLayerProps = {cell: {_subLayerProps: {fill: {type: OffscreenSolidPolygonLayer}}}};
BlurredQuadbinTileLayer.defaultProps._subLayerProps = _subLayerProps;

This approach is conceptually related to the ColorFilterExtension RFC, but it is much more powerful, as it supports effects which sample nearby pixels, allowing for effects like blur, heatmap, edge-detection or any other kernel-based transformation. By contrast the ColorFilterExtension RFC only allows color filters.

Integration

QuadbinHeatmapTileLayer is a drop-in replacement for QuadbinTileLayer with a number of extra props added to control the heatmap:

return new QuadbinHeatmapTileLayer({
  // Heatmap effect props
  palette,
  radius,
  rangeScale,

  // Standard QuadbinTileLayer props
  getFillColor: d => {
    let v = d.properties.population_sum;
    return [v % 256, Math.floor(v / 256), Math.floor(v / (256 * 256)), 0];
  },
  ...
});

Change List

  • Add PostProcessModifier & OffscreenModifier helper functions
  • Add custom heatmap shader module
  • Modify SolidPolygonLayer to output correct screen-normalized value that the heatmap shader module required
  • Add clearTarget option to PostProcessEffect & ScreenPass (only change required to core)
  • Test app

@coveralls
Copy link

coveralls commented Mar 25, 2024

Coverage Status

coverage: 89.83% (-0.2%) from 90.027%
when pulling 1b15be1 on felix/quadbin-heatmap
into 1e53513 on master.

modules/carto/src/layers/heatmap.ts Outdated Show resolved Hide resolved
modules/carto/src/layers/heatmap.ts Show resolved Hide resolved
modules/carto/src/layers/post-process-layer.ts Outdated Show resolved Hide resolved
@@ -44,7 +44,11 @@ export default class PostProcessEffect<ShaderPassT extends ShaderPass> implement
}
const clearCanvas = !renderToTarget || Boolean(params.clearCanvas);
const moduleSettings = {};
moduleSettings[this.module.name] = this.props;
const uniforms = this.module.passes[index].uniforms;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #8801

modules/carto/package.json Outdated Show resolved Hide resolved
test/apps/carto-quadbin-heatmap/app.tsx Outdated Show resolved Hide resolved
modules/carto/src/layers/heatmap.ts Show resolved Hide resolved
@felixpalmer felixpalmer merged commit a287eba into master Apr 29, 2024
4 checks passed
@felixpalmer felixpalmer deleted the felix/quadbin-heatmap branch April 29, 2024 12:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants