@mapgis/supercluster 16.6.0 → 17.0.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.
@@ -0,0 +1,661 @@
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
+ })));
@@ -0,0 +1 @@
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}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mapgis/supercluster",
3
- "version":"16.6.0",
3
+ "version":"17.0.0",
4
4
  "description": "A very fast geospatial point clustering library.",
5
5
  "main": "dist/supercluster.js",
6
6
  "module": "index.js",