Skip to content

Commit

Permalink
CARTO: Move cluster stats into data.points.attributes (#9081)
Browse files Browse the repository at this point in the history
  • Loading branch information
felixpalmer committed Aug 9, 2024
1 parent 4d8d5ef commit 9e0f497
Show file tree
Hide file tree
Showing 6 changed files with 27 additions and 15 deletions.
7 changes: 3 additions & 4 deletions modules/carto/src/layers/cluster-tile-layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,9 @@ class ClusterGeoJsonLayer<

if (needsUpdate) {
const stats = computeAggregationStats(data, properties);
for (const d of data) {
d.stats = stats;
}
this.setState({data: clustersToBinary(data)});
const binaryData = clustersToBinary(data);
binaryData.points.attributes = {stats};
this.setState({data: binaryData});
}

const props = {
Expand Down
14 changes: 12 additions & 2 deletions modules/carto/src/layers/cluster-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ export type ClusteredFeaturePropertiesT<FeaturePropertiesT> = FeaturePropertiesT
id: bigint;
count: number;
position: [number, number];
stats: Record<keyof FeaturePropertiesT, {min: number; max: number}>;
};
export type ParsedQuadbinCell<FeaturePropertiesT> = {id: bigint; properties: FeaturePropertiesT};
export type ParsedQuadbinTile<FeaturePropertiesT> = ParsedQuadbinCell<FeaturePropertiesT>[];
Expand Down Expand Up @@ -142,9 +141,20 @@ const EMPTY_BINARY_PROPS = {
globalFeatureIds: {value: EMPTY_UINT16ARRAY, size: 1}
};

type BinaryFeatureCollectionWithStats<FeaturePropertiesT> = Omit<
BinaryFeatureCollection,
'points'
> & {
points: BinaryFeatureCollection['points'] & {
attributes?: {
stats: Record<keyof FeaturePropertiesT, {min: number; max: number}>;
};
};
};

export function clustersToBinary<FeaturePropertiesT>(
data: ClusteredFeaturePropertiesT<FeaturePropertiesT>[]
): BinaryFeatureCollection {
): BinaryFeatureCollectionWithStats<FeaturePropertiesT> {
const positions = new Float32Array(data.length * 2);
const featureIds = new Uint16Array(data.length);
for (let i = 0; i < data.length; i++) {
Expand Down
4 changes: 2 additions & 2 deletions modules/carto/src/style/color-bins-style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ export default function colorBins<DataT = Feature>({

const color = scaleThreshold<number, Color>().domain(domain).range(palette);

return d => {
const value = getAttrValue(attr, d);
return (d, info) => {
const value = getAttrValue(attr, d, info);
return typeof value === 'number' && Number.isFinite(value) ? color(value) : nullColor;
};
}
4 changes: 2 additions & 2 deletions modules/carto/src/style/color-categories-style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ export default function colorCategories<DataT = Feature>({
colorsByCategory[c] = palette[i];
}

return d => {
const value = getAttrValue(attr, d);
return (d, info) => {
const value = getAttrValue(attr, d, info);
return (typeof value === 'number' && Number.isFinite(value)) || typeof value === 'string'
? colorsByCategory[value] || othersColor
: nullColor;
Expand Down
4 changes: 2 additions & 2 deletions modules/carto/src/style/color-continuous-style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ export default function colorContinuous<DataT = Feature>({
const palette = typeof colors === 'string' ? getPalette(colors, domain.length) : colors;
const color = scaleLinear<Color>().domain(domain).range(palette);

return d => {
const value = getAttrValue(attr, d);
return (d, info) => {
const value = getAttrValue(attr, d, info);
return typeof value === 'number' && Number.isFinite(value) ? color(value) : nullColor;
};
}
9 changes: 6 additions & 3 deletions modules/carto/src/style/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,21 @@ import {assert} from '../utils';

const ALLOWED_ATTR_TYPES = Object.freeze(['function', 'string']);

export type AttributeSelector<DataT = Feature, OutT = any> = string | ((d: DataT) => OutT);
export type AttributeSelector<DataT = Feature, OutT = any> =
| string
| ((d: DataT, info: any) => OutT);

export function getAttrValue<DataT = Feature, OutT = any>(
attr: string | AttributeSelector<DataT, OutT>,
d: DataT
d: DataT,
info: any
): OutT {
assert(typeof d === 'object', 'Expected "data" to be an object');
assert(ALLOWED_ATTR_TYPES.includes(typeof attr), 'Expected "attr" to be a function or string');

// Is function
if (typeof attr === 'function') {
return attr(d);
return attr(d, info);
}
return (d as unknown as Feature)?.properties?.[attr] as OutT;
}

0 comments on commit 9e0f497

Please sign in to comment.