Skip to content

Commit

Permalink
carto: Fix caching in ClusterTileLayer (#9167)
Browse files Browse the repository at this point in the history
  • Loading branch information
zbigg authored and felixpalmer committed Sep 23, 2024
1 parent aec90ee commit feb7bf8
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 5 deletions.
15 changes: 14 additions & 1 deletion modules/carto/src/layers/cluster-tile-layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,14 @@ class ClusterGeoJsonLayer<
clusterIds: bigint[];
hoveredFeatureId: bigint | number | null;
highlightColor: number[];
aggregationCache: WeakMap<any, Map<number, ClusteredFeaturePropertiesT<FeaturePropertiesT>[]>>;
};

initializeState() {
super.initializeState();
this.state.aggregationCache = new WeakMap();
}

renderLayers(): Layer | null | LayersList {
const visibleTiles = this.state.tileset?.tiles.filter((tile: Tile2DHeader) => {
return tile.isLoaded && tile.content && this.state.tileset!.isTileVisible(tile);
Expand All @@ -119,6 +125,7 @@ class ClusterGeoJsonLayer<

const {zoom} = this.context.viewport;
const {clusterLevel, getPosition, getWeight} = this.props;
const {aggregationCache} = this.state;

const properties = extractAggregationProperties(visibleTiles[0]);
const data = [] as ClusteredFeaturePropertiesT<FeaturePropertiesT>[];
Expand All @@ -127,15 +134,21 @@ class ClusterGeoJsonLayer<
// Calculate aggregation based on viewport zoom
const overZoom = Math.round(zoom - tile.zoom);
const aggregationLevels = Math.round(clusterLevel) - overZoom;
let tileAggregationCache = aggregationCache.get(tile.content);
if (!tileAggregationCache) {
tileAggregationCache = new Map();
aggregationCache.set(tile.content, tileAggregationCache);
}
const didAggregate = aggregateTile(
tile,
tileAggregationCache,
aggregationLevels,
properties,
getPosition,
getWeight
);
needsUpdate ||= didAggregate;
data.push(...tile.userData![aggregationLevels]);
data.push(...tileAggregationCache.get(aggregationLevels)!);
}

data.sort((a, b) => Number(b.count - a.count));
Expand Down
9 changes: 5 additions & 4 deletions modules/carto/src/layers/cluster-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export type ParsedQuadbinTile<FeaturePropertiesT> = ParsedQuadbinCell<FeaturePro
*/
export function aggregateTile<FeaturePropertiesT>(
tile: Tile2DHeader<ParsedQuadbinTile<FeaturePropertiesT>>,
tileAggregationCache: Map<number, ClusteredFeaturePropertiesT<FeaturePropertiesT>[]>,
aggregationLevels: number,
properties: AggregationProperties<FeaturePropertiesT> = [],
getPosition: Accessor<ParsedQuadbinCell<FeaturePropertiesT>, [number, number]>,
Expand All @@ -32,7 +33,7 @@ export function aggregateTile<FeaturePropertiesT>(

// Aggregate on demand and cache result
if (!tile.userData) tile.userData = {};
const cell0 = tile.userData[aggregationLevels]?.[0];
const cell0 = tileAggregationCache.get(aggregationLevels)?.[0];
if (cell0) {
// Have already aggregated this tile
if (properties.every(property => property.name in cell0)) {
Expand All @@ -41,15 +42,15 @@ export function aggregateTile<FeaturePropertiesT>(
}

// Aggregated properties have changed, re-aggregate
tile.userData = {};
tileAggregationCache.clear();
}

const out: Record<number, any> = {};
for (const cell of tile.content) {
let id = cell.id;
const position = typeof getPosition === 'function' ? getPosition(cell, {} as any) : getPosition;

// Aggregate by parent id
// Aggregate by parent rid
for (let i = 0; i < aggregationLevels - 1; i++) {
id = cellToParent(id);
}
Expand Down Expand Up @@ -93,7 +94,7 @@ export function aggregateTile<FeaturePropertiesT>(
}
}

tile.userData[aggregationLevels] = Object.values(out);
tileAggregationCache.set(aggregationLevels, Object.values(out));
return true;
}

Expand Down

0 comments on commit feb7bf8

Please sign in to comment.