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: ClusterTileLayer #8957

Merged
merged 9 commits into from
Jun 20, 2024
Merged

CARTO: ClusterTileLayer #8957

merged 9 commits into from
Jun 20, 2024

Conversation

felixpalmer
Copy link
Collaborator

@felixpalmer felixpalmer commented Jun 18, 2024

Background

Implementation of custom layer for CARTO module to allow display of a QuadbinTileLayer as a cluster layer.

Screen.Recording.2024-06-18.at.14.39.24.mov

Implementation

The core layer is a extended TileLayer which rather than rendering a subLayer per tile, collects the visible tiles and re-aggregates the data into clusters. This is quick to do due to the use of the quadbin spatial index.

The resulting aggregated data is rendered using a GeoJsonLayer to easily allow styling of the clusters with a circle, text & icon using a familiar, typed API. For this a conversion to the GeoJsonLayer binary data format is required, but this isn't too expensive as we are only dealing with point data.

Property aggregation

The properties present in the source quadbin data are re-agggregated by inspecting their name, e.g. population_min will be automatically aggregated using the MIN operation, so a cluster will be able to know what the minimum value is for all the cell which it contains. In addition to the re-aggregated properties, the count and stats are available when styling a cluster.

Ahead of time aggregation

When the clusterLevel is sufficiently high, it is often possible for the layer to update the clusters as the zoom level changes before the data is fetched from the server. This gives the impression of responsiveness, as the data is effectively loaded in the background. Thanks to the getPosition accessor it is possible to know where to place each cluster precisely, avoiding the jittery movement of clusters when higher/lower resolution data is fetched

Stats

When the tiles are being aggregated, each of the properties in the cells, (which is eventually present in the cluster) is also aggregated across all the visible data, to easily allow normalization during styling (see example below)

Props

The layer adds three new props to control the aggregation:

  • getPosition called on each quadbin tile to determine the average position
  • getWeight called on each quadbin tile to determine the weight (often will be the count)
  • clusterLevel controls the size of the clusters

In addition, all the GeoJsonLayer props for styling point data are available

Example

new ClusterTileLayer({
  // Aggregation props
  clusterLevel: 5
  getWeight: ({properties}) => properties.lon_count,
  getPosition: ({properties}) => [properties.lon_average, properties.lat_average],

  // Styling props
  pointType: 'circle+icon+text',
  getPointRadius: d => 50 * d.properties.lon_count / d.properties.stats.lon_count, // Scale circles between 0-50 pixels
  pointRadiusUnits: 'pixels',
  getText: d => d.properties.count,
  textSizeScale: 10,
  getIcon: d => d.properties.icon_any,
  ...
});

Change List

  • Addition of ClusterTileLayer
  • cluster-utils for aggregating the quadbin data
  • Types
  • Test app & fetchMap integration (for review only)
  • Type improvements to style helpers (will break out into another PR)

Copy link
Collaborator

@donmccurdy donmccurdy left a comment

Choose a reason for hiding this comment

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

The demo runs very smoothly on my tests — not a blip in the framerate graph! 🚀

My one concern is that we might want to be specific and strict about what the 'weight' means, as that will appear in map legends and be difficult to redefine later.

modules/carto/src/api/layer-map.ts Outdated Show resolved Hide resolved
modules/carto/src/layers/cluster-tile-layer.ts Outdated Show resolved Hide resolved
modules/carto/src/layers/cluster-utils.ts Show resolved Hide resolved
test/apps/carto-quadbin-cluster/app.tsx Outdated Show resolved Hide resolved
modules/carto/src/layers/cluster-utils.ts Outdated Show resolved Hide resolved
@coveralls
Copy link

Coverage Status

coverage: 89.404% (-0.3%) from 89.661%
when pulling d577d8d on felix/tiled-cluster-demo
into 92363b3 on master.

@felixpalmer felixpalmer merged commit 0af27a1 into master Jun 20, 2024
4 checks passed
@felixpalmer felixpalmer deleted the felix/tiled-cluster-demo branch June 20, 2024 08:33
felixpalmer added a commit that referenced this pull request Jul 22, 2024
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.

3 participants