@flowmap.gl/data 8.0.0-alpha.16 → 8.0.0-alpha.17

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.
Files changed (53) hide show
  1. package/{dist-es5 → dist}/FlowmapAggregateAccessors.d.ts +0 -0
  2. package/{dist-es5 → dist}/FlowmapAggregateAccessors.d.ts.map +0 -0
  3. package/dist/FlowmapAggregateAccessors.js +46 -0
  4. package/{dist-es5 → dist}/FlowmapSelectors.d.ts +0 -0
  5. package/{dist-es5 → dist}/FlowmapSelectors.d.ts.map +0 -0
  6. package/dist/FlowmapSelectors.js +887 -0
  7. package/{dist-es5 → dist}/FlowmapState.d.ts +0 -0
  8. package/{dist-es5 → dist}/FlowmapState.d.ts.map +0 -0
  9. package/{dist-es5 → dist}/FlowmapState.js +1 -2
  10. package/{dist-es5 → dist}/cluster/ClusterIndex.d.ts +0 -0
  11. package/{dist-es5 → dist}/cluster/ClusterIndex.d.ts.map +0 -0
  12. package/dist/cluster/ClusterIndex.js +178 -0
  13. package/{dist-es5 → dist}/cluster/cluster.d.ts +0 -0
  14. package/{dist-es5 → dist}/cluster/cluster.d.ts.map +0 -0
  15. package/dist/cluster/cluster.js +211 -0
  16. package/{dist-es5 → dist}/colors.d.ts +0 -0
  17. package/{dist-es5 → dist}/colors.d.ts.map +0 -0
  18. package/dist/colors.js +476 -0
  19. package/{dist-es5 → dist}/getViewStateForLocations.d.ts +0 -0
  20. package/{dist-es5 → dist}/getViewStateForLocations.d.ts.map +0 -0
  21. package/dist/getViewStateForLocations.js +44 -0
  22. package/{dist-es5 → dist}/index.d.ts +0 -0
  23. package/{dist-es5 → dist}/index.d.ts.map +0 -0
  24. package/dist/index.js +10 -0
  25. package/{dist-es5 → dist}/provider/FlowmapDataProvider.d.ts +0 -0
  26. package/{dist-es5 → dist}/provider/FlowmapDataProvider.d.ts.map +0 -0
  27. package/dist/provider/FlowmapDataProvider.js +17 -0
  28. package/{dist-es5 → dist}/provider/LocalFlowmapDataProvider.d.ts +0 -0
  29. package/{dist-es5 → dist}/provider/LocalFlowmapDataProvider.d.ts.map +0 -0
  30. package/dist/provider/LocalFlowmapDataProvider.js +99 -0
  31. package/{dist-es5 → dist}/time.d.ts +0 -0
  32. package/{dist-es5 → dist}/time.d.ts.map +0 -0
  33. package/dist/time.js +126 -0
  34. package/{dist-es5 → dist}/types.d.ts +0 -0
  35. package/{dist-es5 → dist}/types.d.ts.map +0 -0
  36. package/dist/types.js +23 -0
  37. package/{dist-es5 → dist}/util.d.ts +0 -0
  38. package/{dist-es5 → dist}/util.d.ts.map +0 -0
  39. package/dist/util.js +11 -0
  40. package/package.json +5 -7
  41. package/dist-es5/FlowmapAggregateAccessors.js +0 -57
  42. package/dist-es5/FlowmapSelectors.js +0 -1587
  43. package/dist-es5/cluster/ClusterIndex.js +0 -297
  44. package/dist-es5/cluster/cluster.js +0 -278
  45. package/dist-es5/colors.js +0 -510
  46. package/dist-es5/getViewStateForLocations.js +0 -97
  47. package/dist-es5/index.js +0 -28
  48. package/dist-es5/provider/FlowmapDataProvider.js +0 -22
  49. package/dist-es5/provider/LocalFlowmapDataProvider.js +0 -155
  50. package/dist-es5/time.js +0 -168
  51. package/dist-es5/types.js +0 -29
  52. package/dist-es5/util.js +0 -14
  53. package/tsconfig.es5.json +0 -11
File without changes
File without changes
@@ -1,3 +1,2 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
1
+ export {};
3
2
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRmxvd21hcFN0YXRlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL0Zsb3dtYXBTdGF0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtMb2NhdGlvbkZpbHRlck1vZGUsIFZpZXdwb3J0UHJvcHN9IGZyb20gJy4vdHlwZXMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIEZpbHRlclN0YXRlIHtcbiAgc2VsZWN0ZWRMb2NhdGlvbnM6IHN0cmluZ1tdIHwgdW5kZWZpbmVkO1xuICBzZWxlY3RlZFRpbWVSYW5nZTogW0RhdGUsIERhdGVdIHwgdW5kZWZpbmVkO1xuICBsb2NhdGlvbkZpbHRlck1vZGU6IExvY2F0aW9uRmlsdGVyTW9kZTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTZXR0aW5nc1N0YXRlIHtcbiAgYW5pbWF0aW9uRW5hYmxlZDogYm9vbGVhbjtcbiAgZmFkZUVuYWJsZWQ6IGJvb2xlYW47XG4gIGZhZGVPcGFjaXR5RW5hYmxlZDogYm9vbGVhbjtcbiAgbG9jYXRpb25Ub3RhbHNFbmFibGVkOiBib29sZWFuO1xuICBhZGFwdGl2ZVNjYWxlc0VuYWJsZWQ6IGJvb2xlYW47XG4gIGNsdXN0ZXJpbmdFbmFibGVkOiBib29sZWFuO1xuICBjbHVzdGVyaW5nQXV0bzogYm9vbGVhbjtcbiAgY2x1c3RlcmluZ0xldmVsPzogbnVtYmVyO1xuICBkYXJrTW9kZTogYm9vbGVhbjtcbiAgZmFkZUFtb3VudDogbnVtYmVyO1xuICBjb2xvclNjaGVtZTogc3RyaW5nIHwgc3RyaW5nW10gfCB1bmRlZmluZWQ7XG4gIGhpZ2hsaWdodENvbG9yOiBzdHJpbmc7XG4gIG1heFRvcEZsb3dzRGlzcGxheU51bTogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEZsb3dtYXBTdGF0ZSB7XG4gIGZpbHRlclN0YXRlOiBGaWx0ZXJTdGF0ZTtcbiAgc2V0dGluZ3NTdGF0ZTogU2V0dGluZ3NTdGF0ZTtcbiAgdmlld3BvcnQ6IFZpZXdwb3J0UHJvcHM7XG59XG4iXX0=
File without changes
File without changes
@@ -0,0 +1,178 @@
1
+ /*
2
+ * Copyright 2022 FlowmapBlue
3
+ * Copyright 2018-2020 Teralytics, modified by FlowmapBlue
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ *
17
+ */
18
+ import { isCluster, } from './../types';
19
+ import { ascending, bisectLeft, extent } from 'd3-array';
20
+ /**
21
+ * Build ClusterIndex from the given cluster hierarchy
22
+ */
23
+ export function buildIndex(clusterLevels) {
24
+ const nodesByZoom = new Map();
25
+ const clustersById = new Map();
26
+ const minZoomByLocationId = new Map();
27
+ for (const { zoom, nodes } of clusterLevels) {
28
+ nodesByZoom.set(zoom, nodes);
29
+ for (const node of nodes) {
30
+ if (isCluster(node)) {
31
+ clustersById.set(node.id, node);
32
+ }
33
+ else {
34
+ const { id } = node;
35
+ const mz = minZoomByLocationId.get(id);
36
+ if (mz == null || mz > zoom) {
37
+ minZoomByLocationId.set(id, zoom);
38
+ }
39
+ }
40
+ }
41
+ }
42
+ const [minZoom, maxZoom] = extent(clusterLevels, (cl) => cl.zoom);
43
+ if (minZoom == null || maxZoom == null) {
44
+ throw new Error('Could not determine minZoom or maxZoom');
45
+ }
46
+ const leavesToClustersByZoom = new Map();
47
+ for (const cluster of clustersById.values()) {
48
+ const { zoom } = cluster;
49
+ let leavesToClusters = leavesToClustersByZoom.get(zoom);
50
+ if (!leavesToClusters) {
51
+ leavesToClusters = new Map();
52
+ leavesToClustersByZoom.set(zoom, leavesToClusters);
53
+ }
54
+ visitClusterLeaves(cluster, (leafId) => {
55
+ leavesToClusters === null || leavesToClusters === void 0 ? void 0 : leavesToClusters.set(leafId, cluster);
56
+ });
57
+ }
58
+ function visitClusterLeaves(cluster, visit) {
59
+ for (const childId of cluster.children) {
60
+ const child = clustersById.get(childId);
61
+ if (child) {
62
+ visitClusterLeaves(child, visit);
63
+ }
64
+ else {
65
+ visit(childId);
66
+ }
67
+ }
68
+ }
69
+ const expandCluster = (cluster, targetZoom = maxZoom) => {
70
+ const ids = [];
71
+ const visit = (c, expandedIds) => {
72
+ if (targetZoom > c.zoom) {
73
+ for (const childId of c.children) {
74
+ const child = clustersById.get(childId);
75
+ if (child) {
76
+ visit(child, expandedIds);
77
+ }
78
+ else {
79
+ expandedIds.push(childId);
80
+ }
81
+ }
82
+ }
83
+ else {
84
+ expandedIds.push(c.id);
85
+ }
86
+ };
87
+ visit(cluster, ids);
88
+ return ids;
89
+ };
90
+ function findClusterFor(locationId, zoom) {
91
+ const leavesToClusters = leavesToClustersByZoom.get(zoom);
92
+ if (!leavesToClusters) {
93
+ return undefined;
94
+ }
95
+ const cluster = leavesToClusters.get(locationId);
96
+ return cluster ? cluster.id : undefined;
97
+ }
98
+ const availableZoomLevels = clusterLevels
99
+ .map((cl) => +cl.zoom)
100
+ .sort((a, b) => ascending(a, b));
101
+ return {
102
+ availableZoomLevels,
103
+ getClusterNodesFor: (zoom) => {
104
+ if (zoom === undefined) {
105
+ return undefined;
106
+ }
107
+ return nodesByZoom.get(zoom);
108
+ },
109
+ getClusterById: (clusterId) => clustersById.get(clusterId),
110
+ getMinZoomForLocation: (locationId) => minZoomByLocationId.get(locationId) || minZoom,
111
+ expandCluster,
112
+ findClusterFor,
113
+ aggregateFlows: (flows, zoom, { getFlowOriginId, getFlowDestId, getFlowMagnitude }, options = {}) => {
114
+ if (zoom > maxZoom) {
115
+ return flows;
116
+ }
117
+ const result = [];
118
+ const aggFlowsByKey = new Map();
119
+ const makeKey = (origin, dest) => `${origin}:${dest}`;
120
+ const { flowCountsMapReduce = {
121
+ map: getFlowMagnitude,
122
+ reduce: (acc, count) => (acc || 0) + count,
123
+ }, } = options;
124
+ for (const flow of flows) {
125
+ const origin = getFlowOriginId(flow);
126
+ const dest = getFlowDestId(flow);
127
+ const originCluster = findClusterFor(origin, zoom) || origin;
128
+ const destCluster = findClusterFor(dest, zoom) || dest;
129
+ const key = makeKey(originCluster, destCluster);
130
+ if (originCluster === origin && destCluster === dest) {
131
+ result.push(flow);
132
+ }
133
+ else {
134
+ let aggregateFlow = aggFlowsByKey.get(key);
135
+ if (!aggregateFlow) {
136
+ aggregateFlow = {
137
+ origin: originCluster,
138
+ dest: destCluster,
139
+ count: flowCountsMapReduce.map(flow),
140
+ aggregate: true,
141
+ };
142
+ result.push(aggregateFlow);
143
+ aggFlowsByKey.set(key, aggregateFlow);
144
+ }
145
+ else {
146
+ aggregateFlow.count = flowCountsMapReduce.reduce(aggregateFlow.count, flowCountsMapReduce.map(flow));
147
+ }
148
+ }
149
+ }
150
+ return result;
151
+ },
152
+ };
153
+ }
154
+ export function makeLocationWeightGetter(flows, { getFlowOriginId, getFlowDestId, getFlowMagnitude }) {
155
+ const locationTotals = {
156
+ incoming: new Map(),
157
+ outgoing: new Map(),
158
+ };
159
+ for (const flow of flows) {
160
+ const origin = getFlowOriginId(flow);
161
+ const dest = getFlowDestId(flow);
162
+ const count = getFlowMagnitude(flow);
163
+ locationTotals.incoming.set(dest, (locationTotals.incoming.get(dest) || 0) + count);
164
+ locationTotals.outgoing.set(origin, (locationTotals.outgoing.get(origin) || 0) + count);
165
+ }
166
+ return (id) => Math.max(Math.abs(locationTotals.incoming.get(id) || 0), Math.abs(locationTotals.outgoing.get(id) || 0));
167
+ }
168
+ /**
169
+ * @param availableZoomLevels Must be sorted in ascending order
170
+ * @param targetZoom
171
+ */
172
+ export function findAppropriateZoomLevel(availableZoomLevels, targetZoom) {
173
+ if (!availableZoomLevels.length) {
174
+ throw new Error('No available zoom levels');
175
+ }
176
+ return availableZoomLevels[Math.min(bisectLeft(availableZoomLevels, Math.floor(targetZoom)), availableZoomLevels.length - 1)];
177
+ }
178
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ2x1c3RlckluZGV4LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NsdXN0ZXIvQ2x1c3RlckluZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7O0dBZ0JHO0FBRUgsT0FBTyxFQU9MLFNBQVMsR0FDVixNQUFNLFlBQVksQ0FBQztBQUNwQixPQUFPLEVBQUMsU0FBUyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUMsTUFBTSxVQUFVLENBQUM7QUF1Q3ZEOztHQUVHO0FBQ0gsTUFBTSxVQUFVLFVBQVUsQ0FBSSxhQUE0QjtJQUN4RCxNQUFNLFdBQVcsR0FBRyxJQUFJLEdBQUcsRUFBeUIsQ0FBQztJQUNyRCxNQUFNLFlBQVksR0FBRyxJQUFJLEdBQUcsRUFBbUIsQ0FBQztJQUNoRCxNQUFNLG1CQUFtQixHQUFHLElBQUksR0FBRyxFQUFrQixDQUFDO0lBQ3RELEtBQUssTUFBTSxFQUFDLElBQUksRUFBRSxLQUFLLEVBQUMsSUFBSSxhQUFhLEVBQUU7UUFDekMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDN0IsS0FBSyxNQUFNLElBQUksSUFBSSxLQUFLLEVBQUU7WUFDeEIsSUFBSSxTQUFTLENBQUMsSUFBSSxDQUFDLEVBQUU7Z0JBQ25CLFlBQVksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRSxJQUFJLENBQUMsQ0FBQzthQUNqQztpQkFBTTtnQkFDTCxNQUFNLEVBQUMsRUFBRSxFQUFDLEdBQUcsSUFBSSxDQUFDO2dCQUNsQixNQUFNLEVBQUUsR0FBRyxtQkFBbUIsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7Z0JBQ3ZDLElBQUksRUFBRSxJQUFJLElBQUksSUFBSSxFQUFFLEdBQUcsSUFBSSxFQUFFO29CQUMzQixtQkFBbUIsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxDQUFDO2lCQUNuQzthQUNGO1NBQ0Y7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QUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQzlDLElBQUksQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQy9DLENBQUM7QUFDTixDQUFDO0FBRUQ7OztHQUdHO0FBQ0gsTUFBTSxVQUFVLHdCQUF3QixDQUN0QyxtQkFBNkIsRUFDN0IsVUFBa0I7SUFFbEIsSUFBSSxDQUFDLG1CQUFtQixDQUFDLE1BQU0sRUFBRTtRQUMvQixNQUFNLElBQUksS0FBSyxDQUFDLDBCQUEwQixDQUFDLENBQUM7S0FDN0M7SUFDRCxPQUFPLG1CQUFtQixDQUN4QixJQUFJLENBQUMsR0FBRyxDQUNOLFVBQVUsQ0FBQyxtQkFBbUIsRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFDLEVBQ3ZELG1CQUFtQixDQUFDLE1BQU0sR0FBRyxDQUFDLENBQy9CLENBQ0YsQ0FBQztBQUNKLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IDIwMjIgRmxvd21hcEJsdWVcbiAqIENvcHlyaWdodCAyMDE4LTIwMjAgVGVyYWx5dGljcywgbW9kaWZpZWQgYnkgRmxvd21hcEJsdWVcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHtcbiAgQWdncmVnYXRlRmxvdyxcbiAgQ2x1c3RlcixcbiAgQ2x1c3RlckxldmVscyxcbiAgQ2x1c3Rlck5vZGUsXG4gIEZsb3dBY2Nlc3NvcnMsXG4gIEZsb3dDb3VudHNNYXBSZWR1Y2UsXG4gIGlzQ2x1c3Rlcixcbn0gZnJvbSAnLi8uLi90eXBlcyc7XG5pbXBvcnQge2FzY2VuZGluZywgYmlzZWN0TGVmdCwgZXh0ZW50fSBmcm9tICdkMy1hcnJheSc7XG5cbmV4cG9ydCB0eXBlIExvY2F0aW9uV2VpZ2h0R2V0dGVyID0gKGlkOiBzdHJpbmcpID0+IG51bWJlcjtcblxuLyoqXG4gKiBBIGRhdGEgc3RydWN0dXJlIHJlcHJlc2VudGluZyB0aGUgY2x1c3RlciBsZXZlbHMgZm9yIGVmZmljaWVudCBmbG93IGFnZ3JlZ2F0aW9uLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIENsdXN0ZXJJbmRleDxGPiB7XG4gIGF2YWlsYWJsZVpvb21MZXZlbHM6IG51bWJlcltdO1xuICBnZXRDbHVzdGVyQnlJZDogKGNsdXN0ZXJJZDogc3RyaW5nKSA9PiBDbHVzdGVyIHwgdW5kZWZpbmVkO1xuICAvKipcbiAgICogTGlzdCB0aGUgbm9kZXMgb24gdGhlIGdpdmVuIHpvb20gbGV2ZWwuXG4gICAqL1xuICBnZXRDbHVzdGVyTm9kZXNGb3I6ICh6b29tOiBudW1iZXIgfCB1bmRlZmluZWQpID0+IENsdXN0ZXJOb2RlW10gfCB1bmRlZmluZWQ7XG4gIC8qKlxuICAgKiBHZXQgdGhlIG1pbiB6b29tIGxldmVsIG9uIHdoaWNoIHRoZSBsb2NhdGlvbiBpcyBub3QgY2x1c3RlcmVkLlxuICAgKi9cbiAgZ2V0TWluWm9vbUZvckxvY2F0aW9uOiAobG9jYXRpb25JZDogc3RyaW5nKSA9PiBudW1iZXI7XG4gIC8qKlxuICAgKiBMaXN0IHRoZSBJRHMgb2YgYWxsIGxvY2F0aW9ucyBpbiB0aGUgY2x1c3RlciAobGVhdmVzIG9mIHRoZSBzdWJ0cmVlIHN0YXJ0aW5nIGluIHRoZSBjbHVzdGVyKS5cbiAgICovXG4gIGV4cGFuZENsdXN0ZXI6IChjbHVzdGVyOiBDbHVzdGVyLCB0YXJnZXRab29tPzogbnVtYmVyKSA9PiBzdHJpbmdbXTtcbiAgLyoqXG4gICAqIEZpbmQgdGhlIGNsdXN0ZXIgdGhlIGdpdmVuIGxvY2F0aW9uIGlzIHJlc2lkaW5nIGluIG9uIHRoZSBzcGVjaWZpZWQgem9vbSBsZXZlbC5cbiAgICovXG4gIGZpbmRDbHVzdGVyRm9yOiAobG9jYXRpb25JZDogc3RyaW5nLCB6b29tOiBudW1iZXIpID0+IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgLyoqXG4gICAqIEFnZ3JlZ2F0ZSBmbG93cyBmb3IgdGhlIHNwZWNpZmllZCB6b29tIGxldmVsLlxuICAgKi9cbiAgYWdncmVnYXRlRmxvd3M6IChcbiAgICBmbG93czogRltdLFxuICAgIHpvb206IG51bWJlcixcbiAgICB7Z2V0Rmxvd09yaWdpbklkLCBnZXRGbG93RGVzdElkLCBnZXRGbG93TWFnbml0dWRlfTogRmxvd0FjY2Vzc29yczxGPixcbiAgICBvcHRpb25zPzoge1xuICAgICAgZmxvd0NvdW50c01hcFJlZHVjZT86IEZsb3dDb3VudHNNYXBSZWR1Y2U8Rj47XG4gICAgfSxcbiAgKSA9PiAoRiB8IEFnZ3JlZ2F0ZUZsb3cpW107XG59XG5cbi8qKlxuICogQnVpbGQgQ2x1c3RlckluZGV4IGZyb20gdGhlIGdpdmVuIGNsdXN0ZXIgaGllcmFyY2h5XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBidWlsZEluZGV4PEY+KGNsdXN0ZXJMZXZlbHM6IENsdXN0ZXJMZXZlbHMpOiBDbHVzdGVySW5kZXg8Rj4ge1xuICBjb25zdCBub2Rlc0J5Wm9vbSA9IG5ldyBNYXA8bnVtYmVyLCBDbHVzdGVyTm9kZVtdPigpO1xuICBjb25zdCBjbHVzdGVyc0J5SWQgPSBuZXcgTWFwPHN0cmluZywgQ2x1c3Rlcj4oKTtcbiAgY29uc3QgbWluWm9vbUJ5TG9jYXRpb25JZCA9IG5ldyBNYXA8c3RyaW5nLCBudW1iZXI+KCk7XG4gIGZvciAoY29uc3Qge3pvb20sIG5vZGVzfSBvZiBjbHVzdGVyTGV2ZWxzKSB7XG4gICAgbm9kZXNCeVpvb20uc2V0KHpvb20sIG5vZGVzKTtcbiAgICBmb3IgKGNvbnN0IG5vZGUgb2Ygbm9kZXMpIHtcbiAgICAgIGlmIChpc0NsdXN0ZXIobm9kZSkpIHtcbiAgICAgICAgY2x1c3RlcnNCeUlkLnNldChub2RlLmlkLCBub2RlKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnN0IHtpZH0gPSBub2RlO1xuICAgICAgICBjb25zdCBteiA9IG1pblpvb21CeUxvY2F0aW9uSWQuZ2V0KGlkKTtcbiAgICAgICAgaWYgKG16ID09IG51bGwgfHwgbXogPiB6b29tKSB7XG4gICAgICAgICAgbWluWm9vbUJ5TG9jYXRpb25JZC5zZXQoaWQsIHpvb20pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgY29uc3QgW21pblpvb20sIG1heFpvb21dID0gZXh0ZW50KGNsdXN0ZXJMZXZlbHMsIChjbCkgPT4gY2wuem9vbSk7XG4gIGlmIChtaW5ab29tID09IG51bGwgfHwgbWF4Wm9vbSA9PSBudWxsKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdDb3VsZCBub3QgZGV0ZXJtaW5lIG1pblpvb20gb3IgbWF4Wm9vbScpO1xuICB9XG5cbiAgY29uc3QgbGVhdmVzVG9DbHVzdGVyc0J5Wm9vbSA9IG5ldyBNYXA8bnVtYmVyLCBNYXA8c3RyaW5nLCBDbHVzdGVyPj4oKTtcblxuICBmb3IgKGNvbnN0IGNsdXN0ZXIgb2YgY2x1c3RlcnNCeUlkLnZhbHVlcygpKSB7XG4gICAgY29uc3Qge3pvb219ID0gY2x1c3RlcjtcbiAgICBsZXQgbGVhdmVzVG9DbHVzdGVycyA9IGxlYXZlc1RvQ2x1c3RlcnNCeVpvb20uZ2V0KHpvb20pO1xuICAgIGlmICghbGVhdmVzVG9DbHVzdGVycykge1xuICAgICAgbGVhdmVzVG9DbHVzdGVycyA9IG5ldyBNYXA8c3RyaW5nLCBDbHVzdGVyPigpO1xuICAgICAgbGVhdmVzVG9DbHVzdGVyc0J5Wm9vbS5zZXQoem9vbSwgbGVhdmVzVG9DbHVzdGVycyk7XG4gICAgfVxuICAgIHZpc2l0Q2x1c3RlckxlYXZlcyhjbHVzdGVyLCAobGVhZklkKSA9PiB7XG4gICAgICBsZWF2ZXNUb0NsdXN0ZXJzPy5zZXQobGVhZklkLCBjbHVzdGVyKTtcbiAgICB9KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHZpc2l0Q2x1c3RlckxlYXZlcyhjbHVzdGVyOiBDbHVzdGVyLCB2aXNpdDogKGlkOiBzdHJpbmcpID0+IHZvaWQpIHtcbiAgICBmb3IgKGNvbnN0IGNoaWxkSWQgb2YgY2x1c3Rlci5jaGlsZHJlbikge1xuICAgICAgY29uc3QgY2hpbGQgPSBjbHVzdGVyc0J5SWQuZ2V0KGNoaWxkSWQpO1xuICAgICAgaWYgKGNoaWxkKSB7XG4gICAgICAgIHZpc2l0Q2x1c3RlckxlYXZlcyhjaGlsZCwgdmlzaXQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmlzaXQoY2hpbGRJZCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgY29uc3QgZXhwYW5kQ2x1c3RlciA9IChjbHVzdGVyOiBDbHVzdGVyLCB0YXJnZXRab29tOiBudW1iZXIgPSBtYXhab29tKSA9PiB7XG4gICAgY29uc3QgaWRzOiBzdHJpbmdbXSA9IFtdO1xuICAgIGNvbnN0IHZpc2l0ID0gKGM6IENsdXN0ZXIsIGV4cGFuZGVkSWRzOiBzdHJpbmdbXSkgPT4ge1xuICAgICAgaWYgKHRhcmdldFpvb20gPiBjLnpvb20pIHtcbiAgICAgICAgZm9yIChjb25zdCBjaGlsZElkIG9mIGMuY2hpbGRyZW4pIHtcbiAgICAgICAgICBjb25zdCBjaGlsZCA9IGNsdXN0ZXJzQnlJZC5nZXQoY2hpbGRJZCk7XG4gICAgICAgICAgaWYgKGNoaWxkKSB7XG4gICAgICAgICAgICB2aXNpdChjaGlsZCwgZXhwYW5kZWRJZHMpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBleHBhbmRlZElkcy5wdXNoKGNoaWxkSWQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZXhwYW5kZWRJZHMucHVzaChjLmlkKTtcbiAgICAgIH1cbiAgICB9O1xuICAgIHZpc2l0KGNsdXN0ZXIsIGlkcyk7XG4gICAgcmV0dXJuIGlkcztcbiAgfTtcblxuICBmdW5jdGlvbiBmaW5kQ2x1c3RlckZvcihsb2NhdGlvbklkOiBzdHJpbmcsIHpvb206IG51bWJlcikge1xuICAgIGNvbnN0IGxlYXZlc1RvQ2x1c3RlcnMgPSBsZWF2ZXNUb0NsdXN0ZXJzQnlab29tLmdldCh6b29tKTtcbiAgICBpZiAoIWxlYXZlc1RvQ2x1c3RlcnMpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIGNvbnN0IGNsdXN0ZXIgPSBsZWF2ZXNUb0NsdXN0ZXJzLmdldChsb2NhdGlvbklkKTtcbiAgICByZXR1cm4gY2x1c3RlciA/IGNsdXN0ZXIuaWQgOiB1bmRlZmluZWQ7XG4gIH1cblxuICBjb25zdCBhdmFpbGFibGVab29tTGV2ZWxzID0gY2x1c3RlckxldmVsc1xuICAgIC5tYXAoKGNsKSA9PiArY2wuem9vbSlcbiAgICAuc29ydCgoYSwgYikgPT4gYXNjZW5kaW5nKGEsIGIpKTtcblxuICByZXR1cm4ge1xuICAgIGF2YWlsYWJsZVpvb21MZXZlbHMsXG5cbiAgICBnZXRDbHVzdGVyTm9kZXNGb3I6ICh6b29tKSA9PiB7XG4gICAgICBpZiAoem9vbSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgICByZXR1cm4gbm9kZXNCeVpvb20uZ2V0KHpvb20pO1xuICAgIH0sXG5cbiAgICBnZXRDbHVzdGVyQnlJZDogKGNsdXN0ZXJJZCkgPT4gY2x1c3RlcnNCeUlkLmdldChjbHVzdGVySWQpLFxuXG4gICAgZ2V0TWluWm9vbUZvckxvY2F0aW9uOiAobG9jYXRpb25JZCkgPT5cbiAgICAgIG1pblpvb21CeUxvY2F0aW9uSWQuZ2V0KGxvY2F0aW9uSWQpIHx8IG1pblpvb20sXG5cbiAgICBleHBhbmRDbHVzdGVyLFxuXG4gICAgZmluZENsdXN0ZXJGb3IsXG5cbiAgICBhZ2dyZWdhdGVGbG93czogKFxuICAgICAgZmxvd3MsXG4gICAgICB6b29tLFxuICAgICAge2dldEZsb3dPcmlnaW5JZCwgZ2V0Rmxvd0Rlc3RJZCwgZ2V0Rmxvd01hZ25pdHVkZX0sXG4gICAgICBvcHRpb25zID0ge30sXG4gICAgKSA9PiB7XG4gICAgICBpZiAoem9vbSA+IG1heFpvb20pIHtcbiAgICAgICAgcmV0dXJuIGZsb3dzO1xuICAgICAgfVxuICAgICAgY29uc3QgcmVzdWx0OiAoRiB8IEFnZ3JlZ2F0ZUZsb3cpW10gPSBbXTtcbiAgICAgIGNvbnN0IGFnZ0Zsb3dzQnlLZXkgPSBuZXcgTWFwPHN0cmluZywgQWdncmVnYXRlRmxvdz4oKTtcbiAgICAgIGNvbnN0IG1ha2VLZXkgPSAob3JpZ2luOiBzdHJpbmcsIGRlc3Q6IHN0cmluZykgPT4gYCR7b3JpZ2lufToke2Rlc3R9YDtcbiAgICAgIGNvbnN0IHtcbiAgICAgICAgZmxvd0NvdW50c01hcFJlZHVjZSA9IHtcbiAgICAgICAgICBtYXA6IGdldEZsb3dNYWduaXR1ZGUsXG4gICAgICAgICAgcmVkdWNlOiAoYWNjOiBhbnksIGNvdW50OiBudW1iZXIpID0+IChhY2MgfHwgMCkgKyBjb3VudCxcbiAgICAgICAgfSxcbiAgICAgIH0gPSBvcHRpb25zO1xuICAgICAgZm9yIChjb25zdCBmbG93IG9mIGZsb3dzKSB7XG4gICAgICAgIGNvbnN0IG9yaWdpbiA9IGdldEZsb3dPcmlnaW5JZChmbG93KTtcbiAgICAgICAgY29uc3QgZGVzdCA9IGdldEZsb3dEZXN0SWQoZmxvdyk7XG4gICAgICAgIGNvbnN0IG9yaWdpbkNsdXN0ZXIgPSBmaW5kQ2x1c3RlckZvcihvcmlnaW4sIHpvb20pIHx8IG9yaWdpbjtcbiAgICAgICAgY29uc3QgZGVzdENsdXN0ZXIgPSBmaW5kQ2x1c3RlckZvcihkZXN0LCB6b29tKSB8fCBkZXN0O1xuICAgICAgICBjb25zdCBrZXkgPSBtYWtlS2V5KG9yaWdpbkNsdXN0ZXIsIGRlc3RDbHVzdGVyKTtcbiAgICAgICAgaWYgKG9yaWdpbkNsdXN0ZXIgPT09IG9yaWdpbiAmJiBkZXN0Q2x1c3RlciA9PT0gZGVzdCkge1xuICAgICAgICAgIHJlc3VsdC5wdXNoKGZsb3cpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGxldCBhZ2dyZWdhdGVGbG93ID0gYWdnRmxvd3NCeUtleS5nZXQoa2V5KTtcbiAgICAgICAgICBpZiAoIWFnZ3JlZ2F0ZUZsb3cpIHtcbiAgICAgICAgICAgIGFnZ3JlZ2F0ZUZsb3cgPSB7XG4gICAgICAgICAgICAgIG9yaWdpbjogb3JpZ2luQ2x1c3RlcixcbiAgICAgICAgICAgICAgZGVzdDogZGVzdENsdXN0ZXIsXG4gICAgICAgICAgICAgIGNvdW50OiBmbG93Q291bnRzTWFwUmVkdWNlLm1hcChmbG93KSxcbiAgICAgICAgICAgICAgYWdncmVnYXRlOiB0cnVlLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHJlc3VsdC5wdXNoKGFnZ3JlZ2F0ZUZsb3cpO1xuICAgICAgICAgICAgYWdnRmxvd3NCeUtleS5zZXQoa2V5LCBhZ2dyZWdhdGVGbG93KTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYWdncmVnYXRlRmxvdy5jb3VudCA9IGZsb3dDb3VudHNNYXBSZWR1Y2UucmVkdWNlKFxuICAgICAgICAgICAgICBhZ2dyZWdhdGVGbG93LmNvdW50LFxuICAgICAgICAgICAgICBmbG93Q291bnRzTWFwUmVkdWNlLm1hcChmbG93KSxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0sXG4gIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBtYWtlTG9jYXRpb25XZWlnaHRHZXR0ZXI8Rj4oXG4gIGZsb3dzOiBGW10sXG4gIHtnZXRGbG93T3JpZ2luSWQsIGdldEZsb3dEZXN0SWQsIGdldEZsb3dNYWduaXR1ZGV9OiBGbG93QWNjZXNzb3JzPEY+LFxuKTogTG9jYXRpb25XZWlnaHRHZXR0ZXIge1xuICBjb25zdCBsb2NhdGlvblRvdGFscyA9IHtcbiAgICBpbmNvbWluZzogbmV3IE1hcDxzdHJpbmcsIG51bWJlcj4oKSxcbiAgICBvdXRnb2luZzogbmV3IE1hcDxzdHJpbmcsIG51bWJlcj4oKSxcbiAgfTtcbiAgZm9yIChjb25zdCBmbG93IG9mIGZsb3dzKSB7XG4gICAgY29uc3Qgb3JpZ2luID0gZ2V0Rmxvd09yaWdpbklkKGZsb3cpO1xuICAgIGNvbnN0IGRlc3QgPSBnZXRGbG93RGVzdElkKGZsb3cpO1xuICAgIGNvbnN0IGNvdW50ID0gZ2V0Rmxvd01hZ25pdHVkZShmbG93KTtcbiAgICBsb2NhdGlvblRvdGFscy5pbmNvbWluZy5zZXQoXG4gICAgICBkZXN0LFxuICAgICAgKGxvY2F0aW9uVG90YWxzLmluY29taW5nLmdldChkZXN0KSB8fCAwKSArIGNvdW50LFxuICAgICk7XG4gICAgbG9jYXRpb25Ub3RhbHMub3V0Z29pbmcuc2V0KFxuICAgICAgb3JpZ2luLFxuICAgICAgKGxvY2F0aW9uVG90YWxzLm91dGdvaW5nLmdldChvcmlnaW4pIHx8IDApICsgY291bnQsXG4gICAgKTtcbiAgfVxuICByZXR1cm4gKGlkOiBzdHJpbmcpID0+XG4gICAgTWF0aC5tYXgoXG4gICAgICBNYXRoLmFicyhsb2NhdGlvblRvdGFscy5pbmNvbWluZy5nZXQoaWQpIHx8IDApLFxuICAgICAgTWF0aC5hYnMobG9jYXRpb25Ub3RhbHMub3V0Z29pbmcuZ2V0KGlkKSB8fCAwKSxcbiAgICApO1xufVxuXG4vKipcbiAqIEBwYXJhbSBhdmFpbGFibGVab29tTGV2ZWxzIE11c3QgYmUgc29ydGVkIGluIGFzY2VuZGluZyBvcmRlclxuICogQHBhcmFtIHRhcmdldFpvb21cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZpbmRBcHByb3ByaWF0ZVpvb21MZXZlbChcbiAgYXZhaWxhYmxlWm9vbUxldmVsczogbnVtYmVyW10sXG4gIHRhcmdldFpvb206IG51bWJlcixcbikge1xuICBpZiAoIWF2YWlsYWJsZVpvb21MZXZlbHMubGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdObyBhdmFpbGFibGUgem9vbSBsZXZlbHMnKTtcbiAgfVxuICByZXR1cm4gYXZhaWxhYmxlWm9vbUxldmVsc1tcbiAgICBNYXRoLm1pbihcbiAgICAgIGJpc2VjdExlZnQoYXZhaWxhYmxlWm9vbUxldmVscywgTWF0aC5mbG9vcih0YXJnZXRab29tKSksXG4gICAgICBhdmFpbGFibGVab29tTGV2ZWxzLmxlbmd0aCAtIDEsXG4gICAgKVxuICBdO1xufVxuIl19
File without changes
File without changes
@@ -0,0 +1,211 @@
1
+ /*
2
+ * Copyright 2022 FlowmapBlue
3
+ * Copyright 2018-2020 Teralytics, modified by FlowmapBlue
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ *
17
+ */
18
+ /**
19
+ * The code in this file is a based on https://github.com/mapbox/supercluster
20
+ */
21
+ // ISC License
22
+ //
23
+ // Copyright (c) 2016, Mapbox
24
+ //
25
+ // Permission to use, copy, modify, and/or distribute this software for any purpose
26
+ // with or without fee is hereby granted, provided that the above copyright notice
27
+ // and this permission notice appear in all copies.
28
+ //
29
+ // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
30
+ // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
31
+ // FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
32
+ // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
33
+ // OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
34
+ // TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
35
+ // THIS SOFTWARE.
36
+ import { rollup } from 'd3-array';
37
+ import KDBush from 'kdbush';
38
+ const defaultOptions = {
39
+ minZoom: 0,
40
+ maxZoom: 16,
41
+ radius: 40,
42
+ extent: 512,
43
+ nodeSize: 64,
44
+ makeClusterName: (id, numPoints) => undefined,
45
+ makeClusterId: (id) => `{[${id}]}`,
46
+ };
47
+ export function isLeafPoint(p) {
48
+ const { index } = p;
49
+ return index != null;
50
+ }
51
+ export function isClusterPoint(p) {
52
+ const { id } = p;
53
+ return id != null;
54
+ }
55
+ export function clusterLocations(locations, locationAccessors, getLocationWeight, options) {
56
+ const { getLocationLon, getLocationLat, getLocationId } = locationAccessors;
57
+ const opts = Object.assign(Object.assign({}, defaultOptions), options);
58
+ const { minZoom, maxZoom, nodeSize, makeClusterName, makeClusterId } = opts;
59
+ const trees = new Array(maxZoom + 1);
60
+ // generate a cluster object for each point and index input points into a KD-tree
61
+ let clusters = new Array();
62
+ let i = 0;
63
+ for (const location of locations) {
64
+ const x = getLocationLon(location);
65
+ const y = getLocationLat(location);
66
+ clusters.push({
67
+ x: lngX(x),
68
+ y: latY(y),
69
+ weight: getLocationWeight(getLocationId(location)),
70
+ zoom: Infinity,
71
+ index: i,
72
+ parentId: -1,
73
+ location,
74
+ });
75
+ i++;
76
+ }
77
+ trees[maxZoom + 1] = new KDBush(clusters, getX, getY, nodeSize, Float32Array);
78
+ // cluster points on max zoom, then cluster the results on previous zoom, etc.;
79
+ // results in a cluster hierarchy across zoom levels
80
+ for (let z = maxZoom; z >= minZoom; z--) {
81
+ // create a new set of clusters for the zoom and index them with a KD-tree
82
+ clusters = cluster(clusters, z, trees[z + 1], opts);
83
+ trees[z] = new KDBush(clusters, getX, getY, nodeSize, Float32Array);
84
+ }
85
+ if (trees.length === 0) {
86
+ return [];
87
+ }
88
+ const numbersOfClusters = trees.map((d) => d.points.length);
89
+ const maxAvailZoom = numbersOfClusters.indexOf(numbersOfClusters[numbersOfClusters.length - 1]);
90
+ const minAvailZoom = Math.min(maxAvailZoom, numbersOfClusters.lastIndexOf(numbersOfClusters[0]));
91
+ const clusterLevels = new Array();
92
+ for (let zoom = minAvailZoom; zoom <= maxAvailZoom; zoom++) {
93
+ let childrenByParent;
94
+ const tree = trees[zoom];
95
+ if (zoom < maxAvailZoom) {
96
+ childrenByParent = rollup(trees[zoom + 1].points, (points) => points.map((p) => p.id ? makeClusterId(p.id) : getLocationId(p.location)), (point) => point.parentId);
97
+ }
98
+ const nodes = [];
99
+ for (const point of tree.points) {
100
+ const { x, y, numPoints, location } = point;
101
+ if (isLeafPoint(point)) {
102
+ nodes.push({
103
+ id: getLocationId(location),
104
+ zoom,
105
+ lat: getLocationLat(location),
106
+ lon: getLocationLon(location),
107
+ });
108
+ }
109
+ else if (isClusterPoint(point)) {
110
+ const { id } = point;
111
+ const children = childrenByParent && childrenByParent.get(id);
112
+ if (!children) {
113
+ throw new Error(`Cluster ${id} doesn't have children`);
114
+ }
115
+ nodes.push({
116
+ id: makeClusterId(id),
117
+ name: makeClusterName(id, numPoints),
118
+ zoom,
119
+ lat: yLat(y),
120
+ lon: xLng(x),
121
+ children,
122
+ });
123
+ }
124
+ }
125
+ clusterLevels.push({
126
+ zoom,
127
+ nodes,
128
+ });
129
+ }
130
+ return clusterLevels;
131
+ }
132
+ function createCluster(x, y, id, numPoints, weight) {
133
+ return {
134
+ x,
135
+ y,
136
+ zoom: Infinity,
137
+ id,
138
+ parentId: -1,
139
+ numPoints,
140
+ weight,
141
+ };
142
+ }
143
+ function cluster(points, zoom, tree, options) {
144
+ const clusters = [];
145
+ const { radius, extent } = options;
146
+ const r = radius / (extent * Math.pow(2, zoom));
147
+ // loop through each point
148
+ for (let i = 0; i < points.length; i++) {
149
+ const p = points[i];
150
+ // if we've already visited the point at this zoom level, skip it
151
+ if (p.zoom <= zoom) {
152
+ continue;
153
+ }
154
+ p.zoom = zoom;
155
+ // find all nearby points
156
+ const neighborIds = tree.within(p.x, p.y, r);
157
+ let weight = p.weight || 1;
158
+ let numPoints = isClusterPoint(p) ? p.numPoints : 1;
159
+ let wx = p.x * weight;
160
+ let wy = p.y * weight;
161
+ // encode both zoom and point index on which the cluster originated
162
+ const id = (i << 5) + (zoom + 1);
163
+ for (const neighborId of neighborIds) {
164
+ const b = tree.points[neighborId];
165
+ // filter out neighbors that are already processed
166
+ if (b.zoom <= zoom) {
167
+ continue;
168
+ }
169
+ b.zoom = zoom; // save the zoom (so it doesn't get processed twice)
170
+ const weight2 = b.weight || 1;
171
+ const numPoints2 = b.numPoints || 1;
172
+ wx += b.x * weight2; // accumulate coordinates for calculating weighted center
173
+ wy += b.y * weight2;
174
+ weight += weight2;
175
+ numPoints += numPoints2;
176
+ b.parentId = id;
177
+ }
178
+ if (numPoints === 1) {
179
+ clusters.push(p);
180
+ }
181
+ else {
182
+ p.parentId = id;
183
+ clusters.push(createCluster(wx / weight, wy / weight, id, numPoints, weight));
184
+ }
185
+ }
186
+ return clusters;
187
+ }
188
+ // spherical mercator to longitude/latitude
189
+ function xLng(x) {
190
+ return (x - 0.5) * 360;
191
+ }
192
+ function yLat(y) {
193
+ const y2 = ((180 - y * 360) * Math.PI) / 180;
194
+ return (360 * Math.atan(Math.exp(y2))) / Math.PI - 90;
195
+ }
196
+ // longitude/latitude to spherical mercator in [0..1] range
197
+ function lngX(lng) {
198
+ return lng / 360 + 0.5;
199
+ }
200
+ function latY(lat) {
201
+ const sin = Math.sin((lat * Math.PI) / 180);
202
+ const y = 0.5 - (0.25 * Math.log((1 + sin) / (1 - sin))) / Math.PI;
203
+ return y < 0 ? 0 : y > 1 ? 1 : y;
204
+ }
205
+ function getX(p) {
206
+ return p.x;
207
+ }
208
+ function getY(p) {
209
+ return p.y;
210
+ }
211
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jbHVzdGVyL2NsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7R0FnQkc7QUFFSDs7R0FFRztBQUVILGNBQWM7QUFDZCxFQUFFO0FBQ0YsNkJBQTZCO0FBQzdCLEVBQUU7QUFDRixtRkFBbUY7QUFDbkYsa0ZBQWtGO0FBQ2xGLG1EQUFtRDtBQUNuRCxFQUFFO0FBQ0YsZ0ZBQWdGO0FBQ2hGLGtGQUFrRjtBQUNsRiwyRUFBMkU7QUFDM0UsbUZBQW1GO0FBQ25GLGlGQUFpRjtBQUNqRixrRkFBa0Y7QUFDbEYsaUJBQWlCO0FBRWpCLE9BQU8sRUFBQyxNQUFNLEVBQUMsTUFBTSxVQUFVLENBQUM7QUFDaEMsT0FBTyxNQUFNLE1BQU0sUUFBUSxDQUFDO0FBYzVCLE1BQU0sY0FBYyxHQUFZO0lBQzlCLE9BQU8sRUFBRSxDQUFDO0lBQ1YsT0FBTyxFQUFFLEVBQUU7SUFDWCxNQUFNLEVBQUUsRUFBRTtJQUNWLE1BQU0sRUFBRSxHQUFHO0lBQ1gsUUFBUSxFQUFFLEVBQUU7SUFDWixlQUFlLEVBQUUsQ0FBQyxFQUFVLEVBQUUsU0FBaUIsRUFBRSxFQUFFLENBQUMsU0FBUztJQUM3RCxhQUFhLEVBQUUsQ0FBQyxFQUFVLEVBQUUsRUFBRSxDQUFDLEtBQUssRUFBRSxJQUFJO0NBQzNDLENBQUM7QUFzQkYsTUFBTSxVQUFVLFdBQVcsQ0FBSSxDQUFXO0lBQ3hDLE1BQU0sRUFBQyxLQUFLLEVBQUMsR0FBRyxDQUFpQixDQUFDO0lBQ2xDLE9BQU8sS0FBSyxJQUFJLElBQUksQ0FBQztBQUN2QixDQUFDO0FBRUQsTUFBTSxVQUFVLGNBQWMsQ0FBSSxDQUFXO0lBQzNDLE1BQU0sRUFBQyxFQUFFLEVBQUMsR0FBRyxDQUFpQixDQUFDO0lBQy9CLE9BQU8sRUFBRSxJQUFJLElBQUksQ0FBQztBQUNwQixDQUFDO0FBSUQsTUFBTSxVQUFVLGdCQUFn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QUFJLENBQUMsR0FBVztJQUN2QixNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxHQUFHLElBQUksQ0FBQyxFQUFFLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQztJQUM1QyxNQUFNLENBQUMsR0FBRyxHQUFHLEdBQUcsQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQztJQUNuRSxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDbkMsQ0FBQztBQUVELFNBQVMsSUFBSSxDQUFJLENBQVc7SUFDMUIsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ2IsQ0FBQztBQUVELFNBQVMsSUFBSSxDQUFJLENBQVc7SUFDMUIsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ2IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgMjAyMiBGbG93bWFwQmx1ZVxuICogQ29weXJpZ2h0IDIwMTgtMjAyMCBUZXJhbHl0aWNzLCBtb2RpZmllZCBieSBGbG93bWFwQmx1ZVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG4vKipcbiAqIFRoZSBjb2RlIGluIHRoaXMgZmlsZSBpcyBhIGJhc2VkIG9uIGh0dHBzOi8vZ2l0aHViLmNvbS9tYXBib3gvc3VwZXJjbHVzdGVyXG4gKi9cblxuLy8gSVNDIExpY2Vuc2Vcbi8vXG4vLyBDb3B5cmlnaHQgKGMpIDIwMTYsIE1hcGJveFxuLy9cbi8vIFBlcm1pc3Npb24gdG8gdXNlLCBjb3B5LCBtb2RpZnksIGFuZC9vciBkaXN0cmlidXRlIHRoaXMgc29mdHdhcmUgZm9yIGFueSBwdXJwb3NlXG4vLyB3aXRoIG9yIHdpdGhvdXQgZmVlIGlzIGhlcmVieSBncmFudGVkLCBwcm92aWRlZCB0aGF0IHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlXG4vLyBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBhcHBlYXIgaW4gYWxsIGNvcGllcy5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiIEFORCBUSEUgQVVUSE9SIERJU0NMQUlNUyBBTEwgV0FSUkFOVElFUyBXSVRIXG4vLyBSRUdBUkQgVE8gVEhJUyBTT0ZUV0FSRSBJTkNMVURJTkcgQUxMIElNUExJRUQgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFkgQU5EXG4vLyBGSVRORVNTLiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SIEJFIExJQUJMRSBGT1IgQU5ZIFNQRUNJQUwsIERJUkVDVCxcbi8vIElORElSRUNULCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVMgT1IgQU5ZIERBTUFHRVMgV0hBVFNPRVZFUiBSRVNVTFRJTkcgRlJPTSBMT1NTXG4vLyBPRiBVU0UsIERBVEEgT1IgUFJPRklUUywgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIE5FR0xJR0VOQ0UgT1IgT1RIRVJcbi8vIFRPUlRJT1VTIEFDVElPTiwgQVJJU0lORyBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBVU0UgT1IgUEVSRk9STUFOQ0UgT0Zcbi8vIFRISVMgU09GVFdBUkUuXG5cbmltcG9ydCB7cm9sbHVwfSBmcm9tICdkMy1hcnJheSc7XG5pbXBvcnQgS0RCdXNoIGZyb20gJ2tkYnVzaCc7XG5pbXBvcnQge0xvY2F0aW9uV2VpZ2h0R2V0dGVyfSBmcm9tICcuL0NsdXN0ZXJJbmRleCc7XG5pbXBvcnQge0NsdXN0ZXIsIENsdXN0ZXJMZXZlbCwgQ2x1c3Rlck5vZGUsIExvY2F0aW9uQWNjZXNzb3JzfSBmcm9tICcuLi90eXBlcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgT3B0aW9ucyB7XG4gIG1pblpvb206IG51bWJlcjsgLy8gbWluIHpvb20gdG8gZ2VuZXJhdGUgY2x1c3RlcnMgb25cbiAgbWF4Wm9vbTogbnVtYmVyOyAvLyBtYXggem9vbSBsZXZlbCB0byBjbHVzdGVyIHRoZSBwb2ludHMgb25cbiAgcmFkaXVzOiBudW1iZXI7IC8vIGNsdXN0ZXIgcmFkaXVzIGluIHBpeGVsc1xuICBleHRlbnQ6IG51bWJlcjsgLy8gdGlsZSBleHRlbnQgKHJhZGl1cyBpcyBjYWxjdWxhdGVkIHJlbGF0aXZlIHRvIGl0KVxuICBub2RlU2l6ZTogbnVtYmVyOyAvLyBzaXplIG9mIHRoZSBLRC10cmVlIGxlYWYgbm9kZSwgYWZmZWN0cyBwZXJmb3JtYW5jZVxuICBtYWtlQ2x1c3Rlck5hbWU6IChpZDogbnVtYmVyLCBudW1Qb2ludHM6IG51bWJlcikgPT4gc3RyaW5nIHwgdW5kZWZpbmVkO1xuICBtYWtlQ2x1c3RlcklkOiAoaWQ6IG51bWJlcikgPT4gc3RyaW5nO1xufVxuXG5jb25zdCBkZWZhdWx0T3B0aW9uczogT3B0aW9ucyA9IHtcbiAgbWluWm9vbTogMCxcbiAgbWF4Wm9vbTogMTYsXG4gIHJhZGl1czogNDAsXG4gIGV4dGVudDogNTEyLFxuICBub2RlU2l6ZTogNjQsXG4gIG1ha2VDbHVzdGVyTmFtZTogKGlkOiBudW1iZXIsIG51bVBvaW50czogbnVtYmVyKSA9PiB1bmRlZmluZWQsXG4gIG1ha2VDbHVzdGVySWQ6IChpZDogbnVtYmVyKSA9PiBge1ske2lkfV19YCxcbn07XG5cbmludGVyZmFjZSBCYXNlUG9pbnQge1xuICB4OiBudW1iZXI7IC8vIHByb2plY3RlZCBwb2ludCBjb29yZGluYXRlc1xuICB5OiBudW1iZXI7XG4gIHdlaWdodDogbnVtYmVyO1xuICB6b29tOiBudW1iZXI7IC8vIHRoZSBsYXN0IHpvb20gdGhlIHBvaW50IHdhcyBwcm9jZXNzZWQgYXRcbiAgcGFyZW50SWQ6IG51bWJlcjsgLy8gcGFyZW50IGNsdXN0ZXIgaWRcbn1cblxuaW50ZXJmYWNlIExlYWZQb2ludDxMPiBleHRlbmRzIEJhc2VQb2ludCB7XG4gIGluZGV4OiBudW1iZXI7IC8vIGluZGV4IG9mIHRoZSBzb3VyY2UgZmVhdHVyZSBpbiB0aGUgb3JpZ2luYWwgaW5wdXQgYXJyYXksXG4gIGxvY2F0aW9uOiBMO1xufVxuXG5pbnRlcmZhY2UgQ2x1c3RlclBvaW50IGV4dGVuZHMgQmFzZVBvaW50IHtcbiAgaWQ6IG51bWJlcjtcbiAgbnVtUG9pbnRzOiBudW1iZXI7XG59XG5cbnR5cGUgUG9pbnQ8TD4gPSBMZWFmUG9pbnQ8TD4gfCBDbHVzdGVyUG9pbnQ7XG5cbmV4cG9ydCBmdW5jdGlvbiBpc0xlYWZQb2ludDxMPihwOiBQb2ludDxMPik6IHAgaXMgTGVhZlBvaW50PEw+IHtcbiAgY29uc3Qge2luZGV4fSA9IHAgYXMgTGVhZlBvaW50PEw+O1xuICByZXR1cm4gaW5kZXggIT0gbnVsbDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzQ2x1c3RlclBvaW50PEw+KHA6IFBvaW50PEw+KTogcCBpcyBDbHVzdGVyUG9pbnQge1xuICBjb25zdCB7aWR9ID0gcCBhcyBDbHVzdGVyUG9pbnQ7XG4gIHJldHVybiBpZCAhPSBudWxsO1xufVxuXG50eXBlIFpvb21MZXZlbEtEQnVzaCA9IGFueTtcblxuZXhwb3J0IGZ1bmN0aW9uIGNsdXN0ZXJMb2NhdGlvbnM8TD4oXG4gIGxvY2F0aW9uczogSXRlcmFibGU8TD4sXG4gIGxvY2F0aW9uQWNjZXNzb3JzOiBMb2NhdGlvbkFjY2Vzc29yczxMPixcbiAgZ2V0TG9jYXRpb25XZWlnaHQ6IExvY2F0aW9uV2VpZ2h0R2V0dGVyLFxuICBvcHRpb25zPzogUGFydGlhbDxPcHRpb25zPixcbik6IENsdXN0ZXJMZXZlbFtdIHtcbiAgY29uc3Qge2dldExvY2F0aW9uTG9uLCBnZXRMb2NhdGlvbkxhdCwgZ2V0TG9jYXRpb25JZH0gPSBsb2NhdGlvbkFjY2Vzc29ycztcbiAgY29uc3Qgb3B0cyA9IHtcbiAgICAuLi5kZWZhdWx0T3B0aW9ucyxcbiAgICAuLi5vcHRpb25zLFxuICB9O1xuICBjb25zdCB7bWluWm9vbSwgbWF4Wm9vbSwgbm9kZVNpemUsIG1ha2VDbHVzdGVyTmFtZSwgbWFrZUNsdXN0ZXJJZH0gPSBvcHRzO1xuXG4gIGNvbnN0IHRyZWVzID0gbmV3IEFycmF5PFpvb21MZXZlbEtEQnVzaD4obWF4Wm9vbSArIDEpO1xuXG4gIC8vIGdlbmVyYXRlIGEgY2x1c3RlciBvYmplY3QgZm9yIGVhY2ggcG9pbnQgYW5kIGluZGV4IGlucHV0IHBvaW50cyBpbnRvIGEgS0QtdHJlZVxuICBsZXQgY2x1c3RlcnMgPSBuZXcgQXJyYXk8UG9pbnQ8TD4+KCk7XG4gIGxldCBpID0gMDtcbiAgZm9yIChjb25zdCBsb2NhdGlvbiBvZiBsb2NhdGlvbnMpIHtcbiAgICBjb25zdCB4ID0gZ2V0TG9jYXRpb25Mb24obG9jYXRpb24pO1xuICAgIGNvbnN0IHkgPSBnZXRMb2NhdGlvbkxhdChsb2NhdGlvbik7XG4gICAgY2x1c3RlcnMucHVzaCh7XG4gICAgICB4OiBsbmdYKHgpLCAvLyBwcm9qZWN0ZWQgcG9pbnQgY29vcmRpbmF0ZXNcbiAgICAgIHk6IGxhdFkoeSksXG4gICAgICB3ZWlnaHQ6IGdldExvY2F0aW9uV2VpZ2h0KGdldExvY2F0aW9uSWQobG9jYXRpb24pKSxcbiAgICAgIHpvb206IEluZmluaXR5LCAvLyB0aGUgbGFzdCB6b29tIHRoZSBwb2ludCB3YXMgcHJvY2Vzc2VkIGF0XG4gICAgICBpbmRleDogaSwgLy8gaW5kZXggb2YgdGhlIHNvdXJjZSBmZWF0dXJlIGluIHRoZSBvcmlnaW5hbCBpbnB1dCBhcnJheSxcbiAgICAgIHBhcmVudElkOiAtMSwgLy8gcGFyZW50IGNsdXN0ZXIgaWRcbiAgICAgIGxvY2F0aW9uLFxuICAgIH0pO1xuICAgIGkrKztcbiAgfVxuICB0cmVlc1ttYXhab29tICsgMV0gPSBuZXcgS0RCdXNoKGNsdXN0ZXJzLCBnZXRYLCBnZXRZLCBub2RlU2l6ZSwgRmxvYXQzMkFycmF5KTtcblxuICAvLyBjbHVzdGVyIHBvaW50cyBvbiBtYXggem9vbSwgdGhlbiBjbHVzdGVyIHRoZSByZXN1bHRzIG9uIHByZXZpb3VzIHpvb20sIGV0Yy47XG4gIC8vIHJlc3VsdHMgaW4gYSBjbHVzdGVyIGhpZXJhcmNoeSBhY3Jvc3Mgem9vbSBsZXZlbHNcbiAgZm9yIChsZXQgeiA9IG1heFpvb207IHogPj0gbWluWm9vbTsgei0tKSB7XG4gICAgLy8gY3JlYXRlIGEgbmV3IHNldCBvZiBjbHVzdGVycyBmb3IgdGhlIHpvb20gYW5kIGluZGV4IHRoZW0gd2l0aCBhIEtELXRyZWVcbiAgICBjbHVzdGVycyA9IGNsdXN0ZXIoY2x1c3RlcnMsIHosIHRyZWVzW3ogKyAxXSwgb3B0cyk7XG4gICAgdHJlZXNbel0gPSBuZXcgS0RCdXNoKGNsdXN0ZXJzLCBnZXRYLCBnZXRZLCBub2RlU2l6ZSwgRmxvYXQzMkFycmF5KTtcbiAgfVxuXG4gIGlmICh0cmVlcy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gW107XG4gIH1cbiAgY29uc3QgbnVtYmVyc09mQ2x1c3RlcnMgPSB0cmVlcy5tYXAoKGQpID0+IGQucG9pbnRzLmxlbmd0aCk7XG4gIGNvbnN0IG1heEF2YWlsWm9vbSA9IG51bWJlcnNPZkNsdXN0ZXJzLmluZGV4T2YoXG4gICAgbnVtYmVyc09mQ2x1c3RlcnNbbnVtYmVyc09mQ2x1c3RlcnMubGVuZ3RoIC0gMV0sXG4gICk7XG4gIGNvbnN0IG1pbkF2YWlsWm9vbSA9IE1hdGgubWluKFxuICAgIG1heEF2YWlsWm9vbSxcbiAgICBudW1iZXJzT2ZDbHVzdGVycy5sYXN0SW5kZXhPZihudW1iZXJzT2ZDbHVzdGVyc1swXSksXG4gICk7XG5cbiAgY29uc3QgY2x1c3RlckxldmVscyA9IG5ldyBBcnJheTxDbHVzdGVyTGV2ZWw+KCk7XG4gIGZvciAobGV0IHpvb20gPSBtaW5BdmFpbFpvb207IHpvb20gPD0gbWF4QXZhaWxab29tOyB6b29tKyspIHtcbiAgICBsZXQgY2hpbGRyZW5CeVBhcmVudDogTWFwPG51bWJlciwgc3RyaW5nW10+IHwgdW5kZWZpbmVkO1xuICAgIGNvbnN0IHRyZWUgPSB0cmVlc1t6b29tXTtcbiAgICBpZiAoem9vbSA8IG1heEF2YWlsWm9vbSkge1xuICAgICAgY2hpbGRyZW5CeVBhcmVudCA9IHJvbGx1cDxQb2ludDxMPiwgc3RyaW5nW10sIG51bWJlcj4oXG4gICAgICAgIHRyZWVzW3pvb20gKyAxXS5wb2ludHMsXG4gICAgICAgIChwb2ludHM6IGFueVtdKSA9PlxuICAgICAgICAgIHBvaW50cy5tYXAoKHA6IGFueSkgPT5cbiAgICAgICAgICAgIHAuaWQgPyBtYWtlQ2x1c3RlcklkKHAuaWQpIDogZ2V0TG9jYXRpb25JZChwLmxvY2F0aW9uKSxcbiAgICAgICAgICApLFxuICAgICAgICAocG9pbnQ6IGFueSkgPT4gcG9pbnQucGFyZW50SWQsXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IG5vZGVzOiBDbHVzdGVyTm9kZVtdID0gW107XG4gICAgZm9yIChjb25zdCBwb2ludCBvZiB0cmVlLnBvaW50cykge1xuICAgICAgY29uc3Qge3gsIHksIG51bVBvaW50cywgbG9jYXRpb259ID0gcG9pbnQ7XG4gICAgICBpZiAoaXNMZWFmUG9pbnQocG9pbnQpKSB7XG4gICAgICAgIG5vZGVzLnB1c2goe1xuICAgICAgICAgIGlkOiBnZXRMb2NhdGlvbklkKGxvY2F0aW9uKSxcbiAgICAgICAgICB6b29tLFxuICAgICAgICAgIGxhdDogZ2V0TG9jYXRpb25MYXQobG9jYXRpb24pLFxuICAgICAgICAgIGxvbjogZ2V0TG9jYXRpb25Mb24obG9jYXRpb24pLFxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSBpZiAoaXNDbHVzdGVyUG9pbnQocG9pbnQpKSB7XG4gICAgICAgIGNvbnN0IHtpZH0gPSBwb2ludDtcbiAgICAgICAgY29uc3QgY2hpbGRyZW4gPSBjaGlsZHJlbkJ5UGFyZW50ICYmIGNoaWxkcmVuQnlQYXJlbnQuZ2V0KGlkKTtcbiAgICAgICAgaWYgKCFjaGlsZHJlbikge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2x1c3RlciAke2lkfSBkb2Vzbid0IGhhdmUgY2hpbGRyZW5gKTtcbiAgICAgICAgfVxuICAgICAgICBub2Rlcy5wdXNoKHtcbiAgICAgICAgICBpZDogbWFrZUNsdXN0ZXJJZChpZCksXG4gICAgICAgICAgbmFtZTogbWFrZUNsdXN0ZXJOYW1lKGlkLCBudW1Qb2ludHMpLFxuICAgICAgICAgIHpvb20sXG4gICAgICAgICAgbGF0OiB5TGF0KHkpLFxuICAgICAgICAgIGxvbjogeExuZyh4KSxcbiAgICAgICAgICBjaGlsZHJlbixcbiAgICAgICAgfSBhcyBDbHVzdGVyKTtcbiAgICAgIH1cbiAgICB9XG4gICAgY2x1c3RlckxldmVscy5wdXNoKHtcbiAgICAgIHpvb20sXG4gICAgICBub2RlcyxcbiAgICB9KTtcbiAgfVxuICByZXR1cm4gY2x1c3RlckxldmVscztcbn1cblxuZnVuY3Rpb24gY3JlYXRlQ2x1c3RlcihcbiAgeDogbnVtYmVyLFxuICB5OiBudW1iZXIsXG4gIGlkOiBudW1iZXIsXG4gIG51bVBvaW50czogbnVtYmVyLFxuICB3ZWlnaHQ6IG51bWJlcixcbik6IENsdXN0ZXJQb2ludCB7XG4gIHJldHVybiB7XG4gICAgeCwgLy8gd2VpZ2h0ZWQgY2x1c3RlciBjZW50ZXJcbiAgICB5LFxuICAgIHpvb206IEluZmluaXR5LCAvLyB0aGUgbGFzdCB6b29tIHRoZSBjbHVzdGVyIHdhcyBwcm9jZXNzZWQgYXRcbiAgICBpZCwgLy8gZW5jb2RlcyBpbmRleCBvZiB0aGUgZmlyc3QgY2hpbGQgb2YgdGhlIGNsdXN0ZXIgYW5kIGl0cyB6b29tIGxldmVsXG4gICAgcGFyZW50SWQ6IC0xLCAvLyBwYXJlbnQgY2x1c3RlciBpZFxuICAgIG51bVBvaW50cyxcbiAgICB3ZWlnaHQsXG4gIH07XG59XG5cbmZ1bmN0aW9uIGNsdXN0ZXI8TD4oXG4gIHBvaW50czogUG9pbnQ8TD5bXSxcbiAgem9vbTogbnVtYmVyLFxuICB0cmVlOiBab29tTGV2ZWxLREJ1c2gsXG4gIG9wdGlvbnM6IE9wdGlvbnMsXG4pIHtcbiAgY29uc3QgY2x1c3RlcnM6IFBvaW50PEw+W10gPSBbXTtcbiAgY29uc3Qge3JhZGl1cywgZXh0ZW50fSA9IG9wdGlvbnM7XG4gIGNvbnN0IHIgPSByYWRpdXMgLyAoZXh0ZW50ICogTWF0aC5wb3coMiwgem9vbSkpO1xuXG4gIC8vIGxvb3AgdGhyb3VnaCBlYWNoIHBvaW50XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgcG9pbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgY29uc3QgcCA9IHBvaW50c1tpXTtcbiAgICAvLyBpZiB3ZSd2ZSBhbHJlYWR5IHZpc2l0ZWQgdGhlIHBvaW50IGF0IHRoaXMgem9vbSBsZXZlbCwgc2tpcCBpdFxuICAgIGlmIChwLnpvb20gPD0gem9vbSkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIHAuem9vbSA9IHpvb207XG5cbiAgICAvLyBmaW5kIGFsbCBuZWFyYnkgcG9pbnRzXG4gICAgY29uc3QgbmVpZ2hib3JJZHMgPSB0cmVlLndpdGhpbihwLngsIHAueSwgcik7XG5cbiAgICBsZXQgd2VpZ2h0ID0gcC53ZWlnaHQgfHwgMTtcbiAgICBsZXQgbnVtUG9pbnRzID0gaXNDbHVzdGVyUG9pbnQocCkgPyBwLm51bVBvaW50cyA6IDE7XG4gICAgbGV0IHd4ID0gcC54ICogd2VpZ2h0O1xuICAgIGxldCB3eSA9IHAueSAqIHdlaWdodDtcblxuICAgIC8vIGVuY29kZSBib3RoIHpvb20gYW5kIHBvaW50IGluZGV4IG9uIHdoaWNoIHRoZSBjbHVzdGVyIG9yaWdpbmF0ZWRcbiAgICBjb25zdCBpZCA9IChpIDw8IDUpICsgKHpvb20gKyAxKTtcblxuICAgIGZvciAoY29uc3QgbmVpZ2hib3JJZCBvZiBuZWlnaGJvcklkcykge1xuICAgICAgY29uc3QgYiA9IHRyZWUucG9pbnRzW25laWdoYm9ySWRdO1xuICAgICAgLy8gZmlsdGVyIG91dCBuZWlnaGJvcnMgdGhhdCBhcmUgYWxyZWFkeSBwcm9jZXNzZWRcbiAgICAgIGlmIChiLnpvb20gPD0gem9vbSkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGIuem9vbSA9IHpvb207IC8vIHNhdmUgdGhlIHpvb20gKHNvIGl0IGRvZXNuJ3QgZ2V0IHByb2Nlc3NlZCB0d2ljZSlcblxuICAgICAgY29uc3Qgd2VpZ2h0MiA9IGIud2VpZ2h0IHx8IDE7XG4gICAgICBjb25zdCBudW1Qb2ludHMyID0gYi5udW1Qb2ludHMgfHwgMTtcbiAgICAgIHd4ICs9IGIueCAqIHdlaWdodDI7IC8vIGFjY3VtdWxhdGUgY29vcmRpbmF0ZXMgZm9yIGNhbGN1bGF0aW5nIHdlaWdodGVkIGNlbnRlclxuICAgICAgd3kgKz0gYi55ICogd2VpZ2h0MjtcblxuICAgICAgd2VpZ2h0ICs9IHdlaWdodDI7XG4gICAgICBudW1Qb2ludHMgKz0gbnVtUG9pbnRzMjtcbiAgICAgIGIucGFyZW50SWQgPSBpZDtcbiAgICB9XG5cbiAgICBpZiAobnVtUG9pbnRzID09PSAxKSB7XG4gICAgICBjbHVzdGVycy5wdXNoKHApO1xuICAgIH0gZWxzZSB7XG4gICAgICBwLnBhcmVudElkID0gaWQ7XG4gICAgICBjbHVzdGVycy5wdXNoKFxuICAgICAgICBjcmVhdGVDbHVzdGVyKHd4IC8gd2VpZ2h0LCB3eSAvIHdlaWdodCwgaWQsIG51bVBvaW50cywgd2VpZ2h0KSxcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGNsdXN0ZXJzO1xufVxuXG4vLyBzcGhlcmljYWwgbWVyY2F0b3IgdG8gbG9uZ2l0dWRlL2xhdGl0dWRlXG5mdW5jdGlvbiB4TG5nKHg6IG51bWJlcikge1xuICByZXR1cm4gKHggLSAwLjUpICogMzYwO1xufVxuXG5mdW5jdGlvbiB5TGF0KHk6IG51bWJlcikge1xuICBjb25zdCB5MiA9ICgoMTgwIC0geSAqIDM2MCkgKiBNYXRoLlBJKSAvIDE4MDtcbiAgcmV0dXJuICgzNjAgKiBNYXRoLmF0YW4oTWF0aC5leHAoeTIpKSkgLyBNYXRoLlBJIC0gOTA7XG59XG5cbi8vIGxvbmdpdHVkZS9sYXRpdHVkZSB0byBzcGhlcmljYWwgbWVyY2F0b3IgaW4gWzAuLjFdIHJhbmdlXG5mdW5jdGlvbiBsbmdYKGxuZzogbnVtYmVyKSB7XG4gIHJldHVybiBsbmcgLyAzNjAgKyAwLjU7XG59XG5cbmZ1bmN0aW9uIGxhdFkobGF0OiBudW1iZXIpIHtcbiAgY29uc3Qgc2luID0gTWF0aC5zaW4oKGxhdCAqIE1hdGguUEkpIC8gMTgwKTtcbiAgY29uc3QgeSA9IDAuNSAtICgwLjI1ICogTWF0aC5sb2coKDEgKyBzaW4pIC8gKDEgLSBzaW4pKSkgLyBNYXRoLlBJO1xuICByZXR1cm4geSA8IDAgPyAwIDogeSA+IDEgPyAxIDogeTtcbn1cblxuZnVuY3Rpb24gZ2V0WDxMPihwOiBQb2ludDxMPikge1xuICByZXR1cm4gcC54O1xufVxuXG5mdW5jdGlvbiBnZXRZPEw+KHA6IFBvaW50PEw+KSB7XG4gIHJldHVybiBwLnk7XG59XG4iXX0=
File without changes
File without changes