@mapgis/supercluster 16.0.0 → 16.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +53 -54
- package/dist/supercluster.js +0 -661
- package/dist/supercluster.min.js +0 -1
package/package.json
CHANGED
|
@@ -1,54 +1,53 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@mapgis/supercluster",
|
|
3
|
-
|
|
4
|
-
"description": "A very fast geospatial point clustering library.",
|
|
5
|
-
"main": "dist/supercluster.js",
|
|
6
|
-
"module": "index.js",
|
|
7
|
-
"jsdelivr": "dist/supercluster.min.js",
|
|
8
|
-
"unpkg": "dist/supercluster.min.js",
|
|
9
|
-
"scripts": {
|
|
10
|
-
"pretest": "eslint index.js bench.js test/test.js demo/index.js demo/worker.js",
|
|
11
|
-
"test": "tape -r esm test/test.js",
|
|
12
|
-
"cov": "c8 npm run test",
|
|
13
|
-
"bench": "node --expose-gc -r esm bench.js",
|
|
14
|
-
"build": "mkdir dist && rollup -c"
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
"
|
|
19
|
-
"dist/supercluster.js"
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
"
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
"
|
|
38
|
-
"eslint": "^
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"rollup": "^
|
|
43
|
-
"@rollup/plugin-
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
"
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@mapgis/supercluster",
|
|
3
|
+
"version":"16.8.0",
|
|
4
|
+
"description": "A very fast geospatial point clustering library.",
|
|
5
|
+
"main": "dist/supercluster.js",
|
|
6
|
+
"module": "index.js",
|
|
7
|
+
"jsdelivr": "dist/supercluster.min.js",
|
|
8
|
+
"unpkg": "dist/supercluster.min.js",
|
|
9
|
+
"scripts": {
|
|
10
|
+
"pretest": "eslint index.js bench.js test/test.js demo/index.js demo/worker.js",
|
|
11
|
+
"test": "tape -r esm test/test.js",
|
|
12
|
+
"cov": "c8 npm run test",
|
|
13
|
+
"bench": "node --expose-gc -r esm bench.js",
|
|
14
|
+
"build": "mkdir dist && rollup -c"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"index.js",
|
|
18
|
+
"dist/supercluster.js",
|
|
19
|
+
"dist/supercluster.min.js"
|
|
20
|
+
],
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "git://github.com/mapbox/supercluster.git"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"clustering",
|
|
27
|
+
"geospatial",
|
|
28
|
+
"markers"
|
|
29
|
+
],
|
|
30
|
+
"author": "Vladimir Agafonkin",
|
|
31
|
+
"license": "ISC",
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"kdbush": "^3.0.0"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"c8": "^7.1.2",
|
|
37
|
+
"eslint": "^7.1.0",
|
|
38
|
+
"eslint-config-mourner": "^3.0.0",
|
|
39
|
+
"esm": "^3.2.25",
|
|
40
|
+
"mkdirp": "^1.0.4",
|
|
41
|
+
"rollup": "^2.12.0",
|
|
42
|
+
"@rollup/plugin-buble": "^0.21.3",
|
|
43
|
+
"@rollup/plugin-node-resolve": "^8.0.0",
|
|
44
|
+
"rollup-plugin-terser": "^6.1.0",
|
|
45
|
+
"tape": "^5.0.1"
|
|
46
|
+
},
|
|
47
|
+
"eslintConfig": {
|
|
48
|
+
"extends": "mourner",
|
|
49
|
+
"rules": {
|
|
50
|
+
"camelcase": 0
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
package/dist/supercluster.js
DELETED
|
@@ -1,661 +0,0 @@
|
|
|
1
|
-
(function (global, factory) {
|
|
2
|
-
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
|
|
3
|
-
typeof define === 'function' && define.amd ? define(factory) :
|
|
4
|
-
(global = global || self, global.Supercluster = factory());
|
|
5
|
-
}(this, (function () { 'use strict';
|
|
6
|
-
|
|
7
|
-
function sortKD(ids, coords, nodeSize, left, right, depth) {
|
|
8
|
-
if (right - left <= nodeSize) { return; }
|
|
9
|
-
|
|
10
|
-
var m = (left + right) >> 1;
|
|
11
|
-
|
|
12
|
-
select(ids, coords, m, left, right, depth % 2);
|
|
13
|
-
|
|
14
|
-
sortKD(ids, coords, nodeSize, left, m - 1, depth + 1);
|
|
15
|
-
sortKD(ids, coords, nodeSize, m + 1, right, depth + 1);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function select(ids, coords, k, left, right, inc) {
|
|
19
|
-
|
|
20
|
-
while (right > left) {
|
|
21
|
-
if (right - left > 600) {
|
|
22
|
-
var n = right - left + 1;
|
|
23
|
-
var m = k - left + 1;
|
|
24
|
-
var z = Math.log(n);
|
|
25
|
-
var s = 0.5 * Math.exp(2 * z / 3);
|
|
26
|
-
var sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);
|
|
27
|
-
var newLeft = Math.max(left, Math.floor(k - m * s / n + sd));
|
|
28
|
-
var newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));
|
|
29
|
-
select(ids, coords, k, newLeft, newRight, inc);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
var t = coords[2 * k + inc];
|
|
33
|
-
var i = left;
|
|
34
|
-
var j = right;
|
|
35
|
-
|
|
36
|
-
swapItem(ids, coords, left, k);
|
|
37
|
-
if (coords[2 * right + inc] > t) { swapItem(ids, coords, left, right); }
|
|
38
|
-
|
|
39
|
-
while (i < j) {
|
|
40
|
-
swapItem(ids, coords, i, j);
|
|
41
|
-
i++;
|
|
42
|
-
j--;
|
|
43
|
-
while (coords[2 * i + inc] < t) { i++; }
|
|
44
|
-
while (coords[2 * j + inc] > t) { j--; }
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
if (coords[2 * left + inc] === t) { swapItem(ids, coords, left, j); }
|
|
48
|
-
else {
|
|
49
|
-
j++;
|
|
50
|
-
swapItem(ids, coords, j, right);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
if (j <= k) { left = j + 1; }
|
|
54
|
-
if (k <= j) { right = j - 1; }
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
function swapItem(ids, coords, i, j) {
|
|
59
|
-
swap(ids, i, j);
|
|
60
|
-
swap(coords, 2 * i, 2 * j);
|
|
61
|
-
swap(coords, 2 * i + 1, 2 * j + 1);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
function swap(arr, i, j) {
|
|
65
|
-
var tmp = arr[i];
|
|
66
|
-
arr[i] = arr[j];
|
|
67
|
-
arr[j] = tmp;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function range(ids, coords, minX, minY, maxX, maxY, nodeSize) {
|
|
71
|
-
var stack = [0, ids.length - 1, 0];
|
|
72
|
-
var result = [];
|
|
73
|
-
var x, y;
|
|
74
|
-
|
|
75
|
-
while (stack.length) {
|
|
76
|
-
var axis = stack.pop();
|
|
77
|
-
var right = stack.pop();
|
|
78
|
-
var left = stack.pop();
|
|
79
|
-
|
|
80
|
-
if (right - left <= nodeSize) {
|
|
81
|
-
for (var i = left; i <= right; i++) {
|
|
82
|
-
x = coords[2 * i];
|
|
83
|
-
y = coords[2 * i + 1];
|
|
84
|
-
if (x >= minX && x <= maxX && y >= minY && y <= maxY) { result.push(ids[i]); }
|
|
85
|
-
}
|
|
86
|
-
continue;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
var m = Math.floor((left + right) / 2);
|
|
90
|
-
|
|
91
|
-
x = coords[2 * m];
|
|
92
|
-
y = coords[2 * m + 1];
|
|
93
|
-
|
|
94
|
-
if (x >= minX && x <= maxX && y >= minY && y <= maxY) { result.push(ids[m]); }
|
|
95
|
-
|
|
96
|
-
var nextAxis = (axis + 1) % 2;
|
|
97
|
-
|
|
98
|
-
if (axis === 0 ? minX <= x : minY <= y) {
|
|
99
|
-
stack.push(left);
|
|
100
|
-
stack.push(m - 1);
|
|
101
|
-
stack.push(nextAxis);
|
|
102
|
-
}
|
|
103
|
-
if (axis === 0 ? maxX >= x : maxY >= y) {
|
|
104
|
-
stack.push(m + 1);
|
|
105
|
-
stack.push(right);
|
|
106
|
-
stack.push(nextAxis);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
return result;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
function within(ids, coords, qx, qy, r, nodeSize) {
|
|
114
|
-
var stack = [0, ids.length - 1, 0];
|
|
115
|
-
var result = [];
|
|
116
|
-
var r2 = r * r;
|
|
117
|
-
|
|
118
|
-
while (stack.length) {
|
|
119
|
-
var axis = stack.pop();
|
|
120
|
-
var right = stack.pop();
|
|
121
|
-
var left = stack.pop();
|
|
122
|
-
|
|
123
|
-
if (right - left <= nodeSize) {
|
|
124
|
-
for (var i = left; i <= right; i++) {
|
|
125
|
-
if (sqDist(coords[2 * i], coords[2 * i + 1], qx, qy) <= r2) { result.push(ids[i]); }
|
|
126
|
-
}
|
|
127
|
-
continue;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
var m = Math.floor((left + right) / 2);
|
|
131
|
-
|
|
132
|
-
var x = coords[2 * m];
|
|
133
|
-
var y = coords[2 * m + 1];
|
|
134
|
-
|
|
135
|
-
if (sqDist(x, y, qx, qy) <= r2) { result.push(ids[m]); }
|
|
136
|
-
|
|
137
|
-
var nextAxis = (axis + 1) % 2;
|
|
138
|
-
|
|
139
|
-
if (axis === 0 ? qx - r <= x : qy - r <= y) {
|
|
140
|
-
stack.push(left);
|
|
141
|
-
stack.push(m - 1);
|
|
142
|
-
stack.push(nextAxis);
|
|
143
|
-
}
|
|
144
|
-
if (axis === 0 ? qx + r >= x : qy + r >= y) {
|
|
145
|
-
stack.push(m + 1);
|
|
146
|
-
stack.push(right);
|
|
147
|
-
stack.push(nextAxis);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
return result;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
function sqDist(ax, ay, bx, by) {
|
|
155
|
-
var dx = ax - bx;
|
|
156
|
-
var dy = ay - by;
|
|
157
|
-
return dx * dx + dy * dy;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
var defaultGetX = function (p) { return p[0]; };
|
|
161
|
-
var defaultGetY = function (p) { return p[1]; };
|
|
162
|
-
|
|
163
|
-
var KDBush = function KDBush(points, getX, getY, nodeSize, ArrayType) {
|
|
164
|
-
if ( getX === void 0 ) getX = defaultGetX;
|
|
165
|
-
if ( getY === void 0 ) getY = defaultGetY;
|
|
166
|
-
if ( nodeSize === void 0 ) nodeSize = 64;
|
|
167
|
-
if ( ArrayType === void 0 ) ArrayType = Float64Array;
|
|
168
|
-
|
|
169
|
-
this.nodeSize = nodeSize;
|
|
170
|
-
this.points = points;
|
|
171
|
-
|
|
172
|
-
var IndexArrayType = points.length < 65536 ? Uint16Array : Uint32Array;
|
|
173
|
-
|
|
174
|
-
var ids = this.ids = new IndexArrayType(points.length);
|
|
175
|
-
var coords = this.coords = new ArrayType(points.length * 2);
|
|
176
|
-
|
|
177
|
-
for (var i = 0; i < points.length; i++) {
|
|
178
|
-
ids[i] = i;
|
|
179
|
-
coords[2 * i] = getX(points[i]);
|
|
180
|
-
coords[2 * i + 1] = getY(points[i]);
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
sortKD(ids, coords, nodeSize, 0, ids.length - 1, 0);
|
|
184
|
-
};
|
|
185
|
-
|
|
186
|
-
KDBush.prototype.range = function range$1 (minX, minY, maxX, maxY) {
|
|
187
|
-
return range(this.ids, this.coords, minX, minY, maxX, maxY, this.nodeSize);
|
|
188
|
-
};
|
|
189
|
-
|
|
190
|
-
KDBush.prototype.within = function within$1 (x, y, r) {
|
|
191
|
-
return within(this.ids, this.coords, x, y, r, this.nodeSize);
|
|
192
|
-
};
|
|
193
|
-
|
|
194
|
-
var defaultOptions = {
|
|
195
|
-
crs: 'EPSG:3857', // 默认3857
|
|
196
|
-
minZoom: 0, // min zoom to generate clusters on
|
|
197
|
-
maxZoom: 16, // max zoom level to cluster the points on
|
|
198
|
-
minPoints: 2, // minimum points to form a cluster
|
|
199
|
-
radius: 40, // cluster radius in pixels
|
|
200
|
-
extent: 512, // tile extent (radius is calculated relative to it)
|
|
201
|
-
nodeSize: 64, // size of the KD-tree leaf node, affects performance
|
|
202
|
-
log: false, // whether to log timing info
|
|
203
|
-
|
|
204
|
-
// whether to generate numeric ids for input features (in vector tiles)
|
|
205
|
-
generateId: false,
|
|
206
|
-
|
|
207
|
-
// a reduce function for calculating custom cluster properties
|
|
208
|
-
reduce: null, // (accumulated, props) => { accumulated.sum += props.sum; }
|
|
209
|
-
|
|
210
|
-
// properties to use for individual points when running the reducer
|
|
211
|
-
map: function (props) { return props; } // props => ({sum: props.my_value})
|
|
212
|
-
};
|
|
213
|
-
|
|
214
|
-
var Supercluster = function Supercluster(options) {
|
|
215
|
-
this.options = extend(Object.create(defaultOptions), options);
|
|
216
|
-
this.trees = new Array(this.options.maxZoom + 1);
|
|
217
|
-
};
|
|
218
|
-
|
|
219
|
-
Supercluster.prototype.load = function load (points) {
|
|
220
|
-
var ref = this.options;
|
|
221
|
-
var log = ref.log;
|
|
222
|
-
var minZoom = ref.minZoom;
|
|
223
|
-
var maxZoom = ref.maxZoom;
|
|
224
|
-
var nodeSize = ref.nodeSize;
|
|
225
|
-
var crs = ref.crs;
|
|
226
|
-
|
|
227
|
-
if (log) { console.time('total time'); }
|
|
228
|
-
|
|
229
|
-
var timerId = "prepare " + (points.length) + " points";
|
|
230
|
-
if (log) { console.time(timerId); }
|
|
231
|
-
|
|
232
|
-
this.points = points;
|
|
233
|
-
|
|
234
|
-
// generate a cluster object for each point and index input points into a KD-tree
|
|
235
|
-
var clusters = [];
|
|
236
|
-
for (var i = 0; i < points.length; i++) {
|
|
237
|
-
if (!points[i].geometry) { continue; }
|
|
238
|
-
clusters.push(createPointCluster(points[i], i, crs));
|
|
239
|
-
}
|
|
240
|
-
this.trees[maxZoom + 1] = new KDBush(clusters, getX, getY, nodeSize, Float32Array);
|
|
241
|
-
|
|
242
|
-
if (log) { console.timeEnd(timerId); }
|
|
243
|
-
|
|
244
|
-
// cluster points on max zoom, then cluster the results on previous zoom, etc.;
|
|
245
|
-
// results in a cluster hierarchy across zoom levels
|
|
246
|
-
for (var z = maxZoom; z >= minZoom; z--) {
|
|
247
|
-
var now = +Date.now();
|
|
248
|
-
|
|
249
|
-
// create a new set of clusters for the zoom and index them with a KD-tree
|
|
250
|
-
clusters = this._cluster(clusters, z);
|
|
251
|
-
this.trees[z] = new KDBush(clusters, getX, getY, nodeSize, Float32Array);
|
|
252
|
-
|
|
253
|
-
if (log) { console.log('z%d: %d clusters in %dms', z, clusters.length, +Date.now() - now); }
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
if (log) { console.timeEnd('total time'); }
|
|
257
|
-
|
|
258
|
-
return this;
|
|
259
|
-
};
|
|
260
|
-
|
|
261
|
-
Supercluster.prototype.getClusters = function getClusters (bbox, zoom) {
|
|
262
|
-
var crs = this.crs;
|
|
263
|
-
var minLng = ((bbox[0] + 180) % 360 + 360) % 360 - 180;
|
|
264
|
-
var minLat = Math.max(-90, Math.min(90, bbox[1]));
|
|
265
|
-
var maxLng = bbox[2] === 180 ? 180 : ((bbox[2] + 180) % 360 + 360) % 360 - 180;
|
|
266
|
-
var maxLat = Math.max(-90, Math.min(90, bbox[3]));
|
|
267
|
-
|
|
268
|
-
if (bbox[2] - bbox[0] >= 360) {
|
|
269
|
-
minLng = -180;
|
|
270
|
-
maxLng = 180;
|
|
271
|
-
} else if (minLng > maxLng) {
|
|
272
|
-
var easternHem = this.getClusters([minLng, minLat, 180, maxLat], zoom);
|
|
273
|
-
var westernHem = this.getClusters([-180, minLat, maxLng, maxLat], zoom);
|
|
274
|
-
return easternHem.concat(westernHem);
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
var tree = this.trees[this._limitZoom(zoom)];
|
|
278
|
-
var ids = tree.range(lngX(minLng, crs), latY(maxLat, crs), lngX(maxLng, crs), latY(minLat, crs));
|
|
279
|
-
var clusters = [];
|
|
280
|
-
for (var i = 0, list = ids; i < list.length; i += 1) {
|
|
281
|
-
var id = list[i];
|
|
282
|
-
|
|
283
|
-
var c = tree.points[id];
|
|
284
|
-
clusters.push(c.numPoints ? getClusterJSON(c, crs) : this.points[c.index]);
|
|
285
|
-
}
|
|
286
|
-
return clusters;
|
|
287
|
-
};
|
|
288
|
-
|
|
289
|
-
Supercluster.prototype.getChildren = function getChildren (clusterId) {
|
|
290
|
-
var crs = this.crs;
|
|
291
|
-
var originId = this._getOriginId(clusterId);
|
|
292
|
-
var originZoom = this._getOriginZoom(clusterId);
|
|
293
|
-
var errorMsg = 'No cluster with the specified id.';
|
|
294
|
-
|
|
295
|
-
var index = this.trees[originZoom];
|
|
296
|
-
if (!index) { throw new Error(errorMsg); }
|
|
297
|
-
|
|
298
|
-
var origin = index.points[originId];
|
|
299
|
-
if (!origin) { throw new Error(errorMsg); }
|
|
300
|
-
|
|
301
|
-
var r = this.options.radius / (this.options.extent * Math.pow(2, originZoom - 1));
|
|
302
|
-
var ids = index.within(origin.x, origin.y, r);
|
|
303
|
-
var children = [];
|
|
304
|
-
for (var i = 0, list = ids; i < list.length; i += 1) {
|
|
305
|
-
var id = list[i];
|
|
306
|
-
|
|
307
|
-
var c = index.points[id];
|
|
308
|
-
if (c.parentId === clusterId) {
|
|
309
|
-
children.push(c.numPoints ? getClusterJSON(c, crs) : this.points[c.index]);
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
if (children.length === 0) { throw new Error(errorMsg); }
|
|
314
|
-
|
|
315
|
-
return children;
|
|
316
|
-
};
|
|
317
|
-
|
|
318
|
-
Supercluster.prototype.getLeaves = function getLeaves (clusterId, limit, offset) {
|
|
319
|
-
limit = limit || 10;
|
|
320
|
-
offset = offset || 0;
|
|
321
|
-
|
|
322
|
-
var leaves = [];
|
|
323
|
-
this._appendLeaves(leaves, clusterId, limit, offset, 0);
|
|
324
|
-
|
|
325
|
-
return leaves;
|
|
326
|
-
};
|
|
327
|
-
|
|
328
|
-
Supercluster.prototype.getTile = function getTile (z, x, y) {
|
|
329
|
-
var tree = this.trees[this._limitZoom(z)];
|
|
330
|
-
var z2 = Math.pow(2, z);
|
|
331
|
-
var ref = this.options;
|
|
332
|
-
var extent = ref.extent;
|
|
333
|
-
var radius = ref.radius;
|
|
334
|
-
var p = radius / extent;
|
|
335
|
-
var top = (y - p) / z2;
|
|
336
|
-
var bottom = (y + 1 + p) / z2;
|
|
337
|
-
|
|
338
|
-
var tile = {
|
|
339
|
-
features: []
|
|
340
|
-
};
|
|
341
|
-
|
|
342
|
-
this._addTileFeatures(
|
|
343
|
-
tree.range((x - p) / z2, top, (x + 1 + p) / z2, bottom),
|
|
344
|
-
tree.points, x, y, z2, tile);
|
|
345
|
-
|
|
346
|
-
if (x === 0) {
|
|
347
|
-
this._addTileFeatures(
|
|
348
|
-
tree.range(1 - p / z2, top, 1, bottom),
|
|
349
|
-
tree.points, z2, y, z2, tile);
|
|
350
|
-
}
|
|
351
|
-
if (x === z2 - 1) {
|
|
352
|
-
this._addTileFeatures(
|
|
353
|
-
tree.range(0, top, p / z2, bottom),
|
|
354
|
-
tree.points, -1, y, z2, tile);
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
return tile.features.length ? tile : null;
|
|
358
|
-
};
|
|
359
|
-
|
|
360
|
-
Supercluster.prototype.getClusterExpansionZoom = function getClusterExpansionZoom (clusterId) {
|
|
361
|
-
var expansionZoom = this._getOriginZoom(clusterId) - 1;
|
|
362
|
-
while (expansionZoom <= this.options.maxZoom) {
|
|
363
|
-
var children = this.getChildren(clusterId);
|
|
364
|
-
expansionZoom++;
|
|
365
|
-
if (children.length !== 1) { break; }
|
|
366
|
-
clusterId = children[0].properties.cluster_id;
|
|
367
|
-
}
|
|
368
|
-
return expansionZoom;
|
|
369
|
-
};
|
|
370
|
-
|
|
371
|
-
Supercluster.prototype._appendLeaves = function _appendLeaves (result, clusterId, limit, offset, skipped) {
|
|
372
|
-
var children = this.getChildren(clusterId);
|
|
373
|
-
|
|
374
|
-
for (var i = 0, list = children; i < list.length; i += 1) {
|
|
375
|
-
var child = list[i];
|
|
376
|
-
|
|
377
|
-
var props = child.properties;
|
|
378
|
-
|
|
379
|
-
if (props && props.cluster) {
|
|
380
|
-
if (skipped + props.point_count <= offset) {
|
|
381
|
-
// skip the whole cluster
|
|
382
|
-
skipped += props.point_count;
|
|
383
|
-
} else {
|
|
384
|
-
// enter the cluster
|
|
385
|
-
skipped = this._appendLeaves(result, props.cluster_id, limit, offset, skipped);
|
|
386
|
-
// exit the cluster
|
|
387
|
-
}
|
|
388
|
-
} else if (skipped < offset) {
|
|
389
|
-
// skip a single point
|
|
390
|
-
skipped++;
|
|
391
|
-
} else {
|
|
392
|
-
// add a single point
|
|
393
|
-
result.push(child);
|
|
394
|
-
}
|
|
395
|
-
if (result.length === limit) { break; }
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
return skipped;
|
|
399
|
-
};
|
|
400
|
-
|
|
401
|
-
Supercluster.prototype._addTileFeatures = function _addTileFeatures (ids, points, x, y, z2, tile) {
|
|
402
|
-
for (var i$1 = 0, list = ids; i$1 < list.length; i$1 += 1) {
|
|
403
|
-
var i = list[i$1];
|
|
404
|
-
|
|
405
|
-
var c = points[i];
|
|
406
|
-
var isCluster = c.numPoints;
|
|
407
|
-
var f = {
|
|
408
|
-
type: 1,
|
|
409
|
-
geometry: [[
|
|
410
|
-
Math.round(this.options.extent * (c.x * z2 - x)),
|
|
411
|
-
Math.round(this.options.extent * (c.y * z2 - y))
|
|
412
|
-
]],
|
|
413
|
-
tags: isCluster ? getClusterProperties(c) : this.points[c.index].properties
|
|
414
|
-
};
|
|
415
|
-
|
|
416
|
-
// assign id
|
|
417
|
-
var id = (void 0);
|
|
418
|
-
if (isCluster) {
|
|
419
|
-
id = c.id;
|
|
420
|
-
} else if (this.options.generateId) {
|
|
421
|
-
// optionally generate id
|
|
422
|
-
id = c.index;
|
|
423
|
-
} else if (this.points[c.index].id) {
|
|
424
|
-
// keep id if already assigned
|
|
425
|
-
id = this.points[c.index].id;
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
if (id !== undefined) { f.id = id; }
|
|
429
|
-
|
|
430
|
-
tile.features.push(f);
|
|
431
|
-
}
|
|
432
|
-
};
|
|
433
|
-
|
|
434
|
-
Supercluster.prototype._limitZoom = function _limitZoom (z) {
|
|
435
|
-
return Math.max(this.options.minZoom, Math.min(+z, this.options.maxZoom + 1));
|
|
436
|
-
};
|
|
437
|
-
|
|
438
|
-
Supercluster.prototype._cluster = function _cluster (points, zoom) {
|
|
439
|
-
var clusters = [];
|
|
440
|
-
var ref = this.options;
|
|
441
|
-
var radius = ref.radius;
|
|
442
|
-
var extent = ref.extent;
|
|
443
|
-
var reduce = ref.reduce;
|
|
444
|
-
var minPoints = ref.minPoints;
|
|
445
|
-
var r = radius / (extent * Math.pow(2, zoom));
|
|
446
|
-
|
|
447
|
-
// loop through each point
|
|
448
|
-
for (var i = 0; i < points.length; i++) {
|
|
449
|
-
var p = points[i];
|
|
450
|
-
// if we've already visited the point at this zoom level, skip it
|
|
451
|
-
if (p.zoom <= zoom) { continue; }
|
|
452
|
-
p.zoom = zoom;
|
|
453
|
-
|
|
454
|
-
// find all nearby points
|
|
455
|
-
var tree = this.trees[zoom + 1];
|
|
456
|
-
var neighborIds = tree.within(p.x, p.y, r);
|
|
457
|
-
|
|
458
|
-
var numPointsOrigin = p.numPoints || 1;
|
|
459
|
-
var numPoints = numPointsOrigin;
|
|
460
|
-
|
|
461
|
-
// count the number of points in a potential cluster
|
|
462
|
-
for (var i$1 = 0, list = neighborIds; i$1 < list.length; i$1 += 1) {
|
|
463
|
-
var neighborId = list[i$1];
|
|
464
|
-
|
|
465
|
-
var b = tree.points[neighborId];
|
|
466
|
-
// filter out neighbors that are already processed
|
|
467
|
-
if (b.zoom > zoom) { numPoints += b.numPoints || 1; }
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
if (numPoints >= minPoints) { // enough points to form a cluster
|
|
471
|
-
var wx = p.x * numPointsOrigin;
|
|
472
|
-
var wy = p.y * numPointsOrigin;
|
|
473
|
-
|
|
474
|
-
var clusterProperties = reduce && numPointsOrigin > 1 ? this._map(p, true) : null;
|
|
475
|
-
|
|
476
|
-
// encode both zoom and point index on which the cluster originated -- offset by total length of features
|
|
477
|
-
var id = (i << 5) + (zoom + 1) + this.points.length;
|
|
478
|
-
|
|
479
|
-
for (var i$2 = 0, list$1 = neighborIds; i$2 < list$1.length; i$2 += 1) {
|
|
480
|
-
var neighborId$1 = list$1[i$2];
|
|
481
|
-
|
|
482
|
-
var b$1 = tree.points[neighborId$1];
|
|
483
|
-
|
|
484
|
-
if (b$1.zoom <= zoom) { continue; }
|
|
485
|
-
b$1.zoom = zoom; // save the zoom (so it doesn't get processed twice)
|
|
486
|
-
|
|
487
|
-
var numPoints2 = b$1.numPoints || 1;
|
|
488
|
-
wx += b$1.x * numPoints2; // accumulate coordinates for calculating weighted center
|
|
489
|
-
wy += b$1.y * numPoints2;
|
|
490
|
-
|
|
491
|
-
b$1.parentId = id;
|
|
492
|
-
|
|
493
|
-
if (reduce) {
|
|
494
|
-
if (!clusterProperties) { clusterProperties = this._map(p, true); }
|
|
495
|
-
reduce(clusterProperties, this._map(b$1));
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
p.parentId = id;
|
|
500
|
-
clusters.push(createCluster(wx / numPoints, wy / numPoints, id, numPoints, clusterProperties));
|
|
501
|
-
|
|
502
|
-
} else { // left points as unclustered
|
|
503
|
-
clusters.push(p);
|
|
504
|
-
|
|
505
|
-
if (numPoints > 1) {
|
|
506
|
-
for (var i$3 = 0, list$2 = neighborIds; i$3 < list$2.length; i$3 += 1) {
|
|
507
|
-
var neighborId$2 = list$2[i$3];
|
|
508
|
-
|
|
509
|
-
var b$2 = tree.points[neighborId$2];
|
|
510
|
-
if (b$2.zoom <= zoom) { continue; }
|
|
511
|
-
b$2.zoom = zoom;
|
|
512
|
-
clusters.push(b$2);
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
}
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
return clusters;
|
|
519
|
-
};
|
|
520
|
-
|
|
521
|
-
// get index of the point from which the cluster originated
|
|
522
|
-
Supercluster.prototype._getOriginId = function _getOriginId (clusterId) {
|
|
523
|
-
return (clusterId - this.points.length) >> 5;
|
|
524
|
-
};
|
|
525
|
-
|
|
526
|
-
// get zoom of the point from which the cluster originated
|
|
527
|
-
Supercluster.prototype._getOriginZoom = function _getOriginZoom (clusterId) {
|
|
528
|
-
return (clusterId - this.points.length) % 32;
|
|
529
|
-
};
|
|
530
|
-
|
|
531
|
-
Supercluster.prototype._map = function _map (point, clone) {
|
|
532
|
-
if (point.numPoints) {
|
|
533
|
-
return clone ? extend({}, point.properties) : point.properties;
|
|
534
|
-
}
|
|
535
|
-
var original = this.points[point.index].properties;
|
|
536
|
-
var result = this.options.map(original);
|
|
537
|
-
return clone && result === original ? extend({}, result) : result;
|
|
538
|
-
};
|
|
539
|
-
|
|
540
|
-
function createCluster(x, y, id, numPoints, properties) {
|
|
541
|
-
return {
|
|
542
|
-
x: x, // weighted cluster center
|
|
543
|
-
y: y,
|
|
544
|
-
zoom: Infinity, // the last zoom the cluster was processed at
|
|
545
|
-
id: id, // encodes index of the first child of the cluster and its zoom level
|
|
546
|
-
parentId: -1, // parent cluster id
|
|
547
|
-
numPoints: numPoints,
|
|
548
|
-
properties: properties
|
|
549
|
-
};
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
function createPointCluster(p, id, crs) {
|
|
553
|
-
var ref = p.geometry.coordinates;
|
|
554
|
-
var x = ref[0];
|
|
555
|
-
var y = ref[1];
|
|
556
|
-
return {
|
|
557
|
-
x: lngX(x, crs), // projected point coordinates
|
|
558
|
-
y: latY(y, crs),
|
|
559
|
-
zoom: Infinity, // the last zoom the point was processed at
|
|
560
|
-
index: id, // index of the source feature in the original input array,
|
|
561
|
-
parentId: -1 // parent cluster id
|
|
562
|
-
};
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
function getClusterJSON(cluster, crs) {
|
|
566
|
-
return {
|
|
567
|
-
type: 'Feature',
|
|
568
|
-
id: cluster.id,
|
|
569
|
-
properties: getClusterProperties(cluster),
|
|
570
|
-
geometry: {
|
|
571
|
-
type: 'Point',
|
|
572
|
-
coordinates: [xLng(cluster.x, crs), yLat(cluster.y, crs)]
|
|
573
|
-
}
|
|
574
|
-
};
|
|
575
|
-
}
|
|
576
|
-
|
|
577
|
-
function getClusterProperties(cluster) {
|
|
578
|
-
var count = cluster.numPoints;
|
|
579
|
-
var abbrev =
|
|
580
|
-
count >= 10000 ? ((Math.round(count / 1000)) + "k") :
|
|
581
|
-
count >= 1000 ? ((Math.round(count / 100) / 10) + "k") : count;
|
|
582
|
-
return extend(extend({}, cluster.properties), {
|
|
583
|
-
cluster: true,
|
|
584
|
-
cluster_id: cluster.id,
|
|
585
|
-
point_count: count,
|
|
586
|
-
point_count_abbreviated: abbrev
|
|
587
|
-
});
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
/**
|
|
591
|
-
* 针对X方向投影
|
|
592
|
-
* @param {*} lng
|
|
593
|
-
* @param {*} crs
|
|
594
|
-
* @returns 返回投影后的坐标,注意这里的坐标不是平面坐标值,而是矩阵值,即 [0 ~ 1]之间
|
|
595
|
-
*/
|
|
596
|
-
function lngX(lng, crs) {
|
|
597
|
-
var transformX;
|
|
598
|
-
if (!crs || crs === 'EPSG:3857') {
|
|
599
|
-
transformX = lng / 360 + 0.5;
|
|
600
|
-
} else {
|
|
601
|
-
transformX = lng / 360 + 0.5;
|
|
602
|
-
}
|
|
603
|
-
return transformX;
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
/**
|
|
607
|
-
* 针对y方向投影
|
|
608
|
-
* @param {*} lat
|
|
609
|
-
* @param {*} crs
|
|
610
|
-
* @returns 返回投影后的坐标,注意这里的坐标不是平面坐标值,而是矩阵值,即 [0 ~ 1]之间
|
|
611
|
-
*/
|
|
612
|
-
function latY(lat, crs) {
|
|
613
|
-
var transformY;
|
|
614
|
-
if (!crs || crs === 'EPSG:3857') {
|
|
615
|
-
var sin = Math.sin(lat * Math.PI / 180);
|
|
616
|
-
transformY = 0.5 - 0.25 * Math.log((1 + sin) / (1 - sin)) / Math.PI;
|
|
617
|
-
} else {
|
|
618
|
-
transformY = (90 - lat) / 360;
|
|
619
|
-
}
|
|
620
|
-
return transformY < 0 ? 0 : transformY > 1 ? 1 : transformY;
|
|
621
|
-
/* const sin = Math.sin(lat * Math.PI / 180);
|
|
622
|
-
const y = (0.5 - 0.25 * Math.log((1 + sin) / (1 - sin)) / Math.PI);
|
|
623
|
-
return y < 0 ? 0 : y > 1 ? 1 : y; */
|
|
624
|
-
}
|
|
625
|
-
|
|
626
|
-
// spherical mercator to longitude/latitude
|
|
627
|
-
function xLng(x, crs) {
|
|
628
|
-
if (!crs || crs === 'EPSG:3857') {
|
|
629
|
-
return (x - 0.5) * 360;
|
|
630
|
-
} else {
|
|
631
|
-
return (x - 0.5) * 360;
|
|
632
|
-
}
|
|
633
|
-
// return (x - 0.5) * 360;
|
|
634
|
-
}
|
|
635
|
-
function yLat(y, crs) {
|
|
636
|
-
if (!crs || crs === 'EPSG:3857') {
|
|
637
|
-
var y2 = (180 - y * 360) * Math.PI / 180;
|
|
638
|
-
return 360 * Math.atan(Math.exp(y2)) / Math.PI - 90;
|
|
639
|
-
} else {
|
|
640
|
-
return 90 - (y * 360);
|
|
641
|
-
}
|
|
642
|
-
|
|
643
|
-
// const y2 = (180 - y * 360) * Math.PI / 180;
|
|
644
|
-
// return 360 * Math.atan(Math.exp(y2)) / Math.PI - 90;
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
function extend(dest, src) {
|
|
648
|
-
for (var id in src) { dest[id] = src[id]; }
|
|
649
|
-
return dest;
|
|
650
|
-
}
|
|
651
|
-
|
|
652
|
-
function getX(p) {
|
|
653
|
-
return p.x;
|
|
654
|
-
}
|
|
655
|
-
function getY(p) {
|
|
656
|
-
return p.y;
|
|
657
|
-
}
|
|
658
|
-
|
|
659
|
-
return Supercluster;
|
|
660
|
-
|
|
661
|
-
})));
|
package/dist/supercluster.min.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
!function(t,o){"object"==typeof exports&&"undefined"!=typeof module?module.exports=o():"function"==typeof define&&define.amd?define(o):(t=t||self).Supercluster=o()}(this,(function(){"use strict";function t(e,n,r,i,s,a){if(!(s-i<=r)){var p=i+s>>1;!function t(e,n,r,i,s,a){for(;s>i;){if(s-i>600){var p=s-i+1,h=r-i+1,u=Math.log(p),f=.5*Math.exp(2*u/3),d=.5*Math.sqrt(u*f*(p-f)/p)*(h-p/2<0?-1:1),l=Math.max(i,Math.floor(r-h*f/p+d)),c=Math.min(s,Math.floor(r+(p-h)*f/p+d));t(e,n,r,l,c,a)}var m=n[2*r+a],v=i,g=s;for(o(e,n,i,r),n[2*s+a]>m&&o(e,n,i,s);v<g;){for(o(e,n,v,g),v++,g--;n[2*v+a]<m;)v++;for(;n[2*g+a]>m;)g--}n[2*i+a]===m?o(e,n,i,g):(g++,o(e,n,g,s)),g<=r&&(i=g+1),r<=g&&(s=g-1)}}(e,n,p,i,s,a%2),t(e,n,r,i,p-1,a+1),t(e,n,r,p+1,s,a+1)}}function o(t,o,n,r){e(t,n,r),e(o,2*n,2*r),e(o,2*n+1,2*r+1)}function e(t,o,e){var n=t[o];t[o]=t[e],t[e]=n}function n(t,o,e,n){var r=t-e,i=o-n;return r*r+i*i}var r=function(t){return t[0]},i=function(t){return t[1]},s=function(o,e,n,s,a){void 0===e&&(e=r),void 0===n&&(n=i),void 0===s&&(s=64),void 0===a&&(a=Float64Array),this.nodeSize=s,this.points=o;for(var p=o.length<65536?Uint16Array:Uint32Array,h=this.ids=new p(o.length),u=this.coords=new a(2*o.length),f=0;f<o.length;f++)h[f]=f,u[2*f]=e(o[f]),u[2*f+1]=n(o[f]);t(h,u,s,0,h.length-1,0)};s.prototype.range=function(t,o,e,n){return function(t,o,e,n,r,i,s){for(var a,p,h=[0,t.length-1,0],u=[];h.length;){var f=h.pop(),d=h.pop(),l=h.pop();if(d-l<=s)for(var c=l;c<=d;c++)a=o[2*c],p=o[2*c+1],a>=e&&a<=r&&p>=n&&p<=i&&u.push(t[c]);else{var m=Math.floor((l+d)/2);a=o[2*m],p=o[2*m+1],a>=e&&a<=r&&p>=n&&p<=i&&u.push(t[m]);var v=(f+1)%2;(0===f?e<=a:n<=p)&&(h.push(l),h.push(m-1),h.push(v)),(0===f?r>=a:i>=p)&&(h.push(m+1),h.push(d),h.push(v))}}return u}(this.ids,this.coords,t,o,e,n,this.nodeSize)},s.prototype.within=function(t,o,e){return function(t,o,e,r,i,s){for(var a=[0,t.length-1,0],p=[],h=i*i;a.length;){var u=a.pop(),f=a.pop(),d=a.pop();if(f-d<=s)for(var l=d;l<=f;l++)n(o[2*l],o[2*l+1],e,r)<=h&&p.push(t[l]);else{var c=Math.floor((d+f)/2),m=o[2*c],v=o[2*c+1];n(m,v,e,r)<=h&&p.push(t[c]);var g=(u+1)%2;(0===u?e-i<=m:r-i<=v)&&(a.push(d),a.push(c-1),a.push(g)),(0===u?e+i>=m:r+i>=v)&&(a.push(c+1),a.push(f),a.push(g))}}return p}(this.ids,this.coords,t,o,e,this.nodeSize)};var a={crs:"EPSG:3857",minZoom:0,maxZoom:16,minPoints:2,radius:40,extent:512,nodeSize:64,log:!1,generateId:!1,reduce:null,map:function(t){return t}},p=function(t){this.options=g(Object.create(a),t),this.trees=new Array(this.options.maxZoom+1)};function h(t,o,e,n,r){return{x:t,y:o,zoom:1/0,id:e,parentId:-1,numPoints:n,properties:r}}function u(t,o,e){var n=t.geometry.coordinates,r=n[0],i=n[1];return{x:l(r,e),y:c(i,e),zoom:1/0,index:o,parentId:-1}}function f(t,o){return{type:"Feature",id:t.id,properties:d(t),geometry:{type:"Point",coordinates:[m(t.x,o),v(t.y,o)]}}}function d(t){var o=t.numPoints,e=o>=1e4?Math.round(o/1e3)+"k":o>=1e3?Math.round(o/100)/10+"k":o;return g(g({},t.properties),{cluster:!0,cluster_id:t.id,point_count:o,point_count_abbreviated:e})}function l(t,o){return t/360+.5}function c(t,o){var e;if(o&&"EPSG:3857"!==o)e=(90-t)/360;else{var n=Math.sin(t*Math.PI/180);e=.5-.25*Math.log((1+n)/(1-n))/Math.PI}return e<0?0:e>1?1:e}function m(t,o){return 360*(t-.5)}function v(t,o){if(o&&"EPSG:3857"!==o)return 90-360*t;var e=(180-360*t)*Math.PI/180;return 360*Math.atan(Math.exp(e))/Math.PI-90}function g(t,o){for(var e in o)t[e]=o[e];return t}function y(t){return t.x}function x(t){return t.y}return p.prototype.load=function(t){var o=this.options,e=o.log,n=o.minZoom,r=o.maxZoom,i=o.nodeSize,a=o.crs;e&&console.time("total time");var p="prepare "+t.length+" points";e&&console.time(p),this.points=t;for(var h=[],f=0;f<t.length;f++)t[f].geometry&&h.push(u(t[f],f,a));this.trees[r+1]=new s(h,y,x,i,Float32Array),e&&console.timeEnd(p);for(var d=r;d>=n;d--){var l=+Date.now();h=this._cluster(h,d),this.trees[d]=new s(h,y,x,i,Float32Array),e&&console.log("z%d: %d clusters in %dms",d,h.length,+Date.now()-l)}return e&&console.timeEnd("total time"),this},p.prototype.getClusters=function(t,o){var e=this.crs,n=((t[0]+180)%360+360)%360-180,r=Math.max(-90,Math.min(90,t[1])),i=180===t[2]?180:((t[2]+180)%360+360)%360-180,s=Math.max(-90,Math.min(90,t[3]));if(t[2]-t[0]>=360)n=-180,i=180;else if(n>i){var a=this.getClusters([n,r,180,s],o),p=this.getClusters([-180,r,i,s],o);return a.concat(p)}for(var h=this.trees[this._limitZoom(o)],u=[],d=0,m=h.range(l(n,e),c(s,e),l(i,e),c(r,e));d<m.length;d+=1){var v=m[d],g=h.points[v];u.push(g.numPoints?f(g,e):this.points[g.index])}return u},p.prototype.getChildren=function(t){var o=this.crs,e=this._getOriginId(t),n=this._getOriginZoom(t),r="No cluster with the specified id.",i=this.trees[n];if(!i)throw new Error(r);var s=i.points[e];if(!s)throw new Error(r);for(var a=this.options.radius/(this.options.extent*Math.pow(2,n-1)),p=[],h=0,u=i.within(s.x,s.y,a);h<u.length;h+=1){var d=u[h],l=i.points[d];l.parentId===t&&p.push(l.numPoints?f(l,o):this.points[l.index])}if(0===p.length)throw new Error(r);return p},p.prototype.getLeaves=function(t,o,e){o=o||10,e=e||0;var n=[];return this._appendLeaves(n,t,o,e,0),n},p.prototype.getTile=function(t,o,e){var n=this.trees[this._limitZoom(t)],r=Math.pow(2,t),i=this.options,s=i.extent,a=i.radius/s,p=(e-a)/r,h=(e+1+a)/r,u={features:[]};return this._addTileFeatures(n.range((o-a)/r,p,(o+1+a)/r,h),n.points,o,e,r,u),0===o&&this._addTileFeatures(n.range(1-a/r,p,1,h),n.points,r,e,r,u),o===r-1&&this._addTileFeatures(n.range(0,p,a/r,h),n.points,-1,e,r,u),u.features.length?u:null},p.prototype.getClusterExpansionZoom=function(t){for(var o=this._getOriginZoom(t)-1;o<=this.options.maxZoom;){var e=this.getChildren(t);if(o++,1!==e.length)break;t=e[0].properties.cluster_id}return o},p.prototype._appendLeaves=function(t,o,e,n,r){for(var i=0,s=this.getChildren(o);i<s.length;i+=1){var a=s[i],p=a.properties;if(p&&p.cluster?r+p.point_count<=n?r+=p.point_count:r=this._appendLeaves(t,p.cluster_id,e,n,r):r<n?r++:t.push(a),t.length===e)break}return r},p.prototype._addTileFeatures=function(t,o,e,n,r,i){for(var s=0,a=t;s<a.length;s+=1){var p=o[a[s]],h=p.numPoints,u={type:1,geometry:[[Math.round(this.options.extent*(p.x*r-e)),Math.round(this.options.extent*(p.y*r-n))]],tags:h?d(p):this.points[p.index].properties},f=void 0;h?f=p.id:this.options.generateId?f=p.index:this.points[p.index].id&&(f=this.points[p.index].id),void 0!==f&&(u.id=f),i.features.push(u)}},p.prototype._limitZoom=function(t){return Math.max(this.options.minZoom,Math.min(+t,this.options.maxZoom+1))},p.prototype._cluster=function(t,o){for(var e=[],n=this.options,r=n.radius,i=n.extent,s=n.reduce,a=n.minPoints,p=r/(i*Math.pow(2,o)),u=0;u<t.length;u++){var f=t[u];if(!(f.zoom<=o)){f.zoom=o;for(var d=this.trees[o+1],l=d.within(f.x,f.y,p),c=f.numPoints||1,m=c,v=0,g=l;v<g.length;v+=1){var y=g[v],x=d.points[y];x.zoom>o&&(m+=x.numPoints||1)}if(m>=a){for(var M=f.x*c,_=f.y*c,w=s&&c>1?this._map(f,!0):null,P=(u<<5)+(o+1)+this.points.length,z=0,Z=l;z<Z.length;z+=1){var I=Z[z],E=d.points[I];if(!(E.zoom<=o)){E.zoom=o;var S=E.numPoints||1;M+=E.x*S,_+=E.y*S,E.parentId=P,s&&(w||(w=this._map(f,!0)),s(w,this._map(E)))}}f.parentId=P,e.push(h(M/m,_/m,P,m,w))}else if(e.push(f),m>1)for(var F=0,C=l;F<C.length;F+=1){var b=C[F],A=d.points[b];A.zoom<=o||(A.zoom=o,e.push(A))}}}return e},p.prototype._getOriginId=function(t){return t-this.points.length>>5},p.prototype._getOriginZoom=function(t){return(t-this.points.length)%32},p.prototype._map=function(t,o){if(t.numPoints)return o?g({},t.properties):t.properties;var e=this.points[t.index].properties,n=this.options.map(e);return o&&n===e?g({},n):n},p}));
|