Skip to content

Commit 3f70aac

Browse files
committed
Add support for weighted cluster point calculation
Basically just adopted mapbox#119 by @ilyabo on latest main
1 parent 7c5859e commit 3f70aac

File tree

1 file changed

+18
-10
lines changed

1 file changed

+18
-10
lines changed

index.js

+18-10
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,14 @@ const OFFSET_ZOOM = 2;
2626
const OFFSET_ID = 3;
2727
const OFFSET_PARENT = 4;
2828
const OFFSET_NUM = 5;
29-
const OFFSET_PROP = 6;
29+
const OFFSET_WEIGHT = 6;
30+
const OFFSET_PROP = 7;
3031

3132
export default class Supercluster {
3233
constructor(options) {
3334
this.options = Object.assign(Object.create(defaultOptions), options);
3435
this.trees = new Array(this.options.maxZoom + 1);
35-
this.stride = this.options.reduce ? 7 : 6;
36+
this.stride = OFFSET_PROP + (this.options.reduce ? 1 : 0);
3637
this.clusterProps = [];
3738
}
3839

@@ -62,7 +63,8 @@ export default class Supercluster {
6263
Infinity, // the last zoom the point was processed at
6364
i, // index of the source feature in the original input array
6465
-1, // parent cluster id
65-
1 // number of points in a cluster
66+
1, // number of points in a cluster
67+
p.properties.weight ?? 1 // cluster weight
6668
);
6769
if (this.options.reduce) data.push(0); // noop
6870
}
@@ -295,17 +297,23 @@ export default class Supercluster {
295297
const numPointsOrigin = data[i + OFFSET_NUM];
296298
let numPoints = numPointsOrigin;
297299

300+
const pointsWeightOrigin = data[i + OFFSET_WEIGHT];
301+
let pointsWeight = pointsWeightOrigin;
302+
298303
// count the number of points in a potential cluster
299304
for (const neighborId of neighborIds) {
300305
const k = neighborId * stride;
301306
// filter out neighbors that are already processed
302-
if (data[k + OFFSET_ZOOM] > zoom) numPoints += data[k + OFFSET_NUM];
307+
if (data[k + OFFSET_ZOOM] > zoom) {
308+
numPoints += data[k + OFFSET_NUM];
309+
pointsWeight += data[k + OFFSET_WEIGHT];
310+
}
303311
}
304312

305313
// if there were neighbors to merge, and there are enough points to form a cluster
306314
if (numPoints > numPointsOrigin && numPoints >= minPoints) {
307-
let wx = x * numPointsOrigin;
308-
let wy = y * numPointsOrigin;
315+
let wx = x * pointsWeightOrigin;
316+
let wy = y * pointsWeightOrigin;
309317

310318
let clusterProperties;
311319
let clusterPropIndex = -1;
@@ -319,9 +327,9 @@ export default class Supercluster {
319327
if (data[k + OFFSET_ZOOM] <= zoom) continue;
320328
data[k + OFFSET_ZOOM] = zoom; // save the zoom (so it doesn't get processed twice)
321329

322-
const numPoints2 = data[k + OFFSET_NUM];
323-
wx += data[k] * numPoints2; // accumulate coordinates for calculating weighted center
324-
wy += data[k + 1] * numPoints2;
330+
const pointsWeight2 = data[k + OFFSET_WEIGHT];
331+
wx += data[k] * pointsWeight2; // accumulate coordinates for calculating weighted position
332+
wy += data[k + 1] * pointsWeight2;
325333

326334
data[k + OFFSET_PARENT] = id;
327335

@@ -336,7 +344,7 @@ export default class Supercluster {
336344
}
337345

338346
data[i + OFFSET_PARENT] = id;
339-
nextData.push(wx / numPoints, wy / numPoints, Infinity, id, -1, numPoints);
347+
nextData.push(wx / pointsWeight, wy / pointsWeight, Infinity, id, -1, numPoints, pointsWeight);
340348
if (reduce) nextData.push(clusterPropIndex);
341349

342350
} else { // left points as unclustered

0 commit comments

Comments
 (0)