cesium-alpha-earth 1.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.
- package/dist/index.js +214371 -0
- package/index.html +16 -0
- package/package.json +29 -0
- package/src/core/CesiumAlphaGeoJsonLayer/index.ts +815 -0
- package/src/core/CesiumAlphaGeoJsonLayer/method/geojson-util.ts +374 -0
- package/src/core/CesiumAlphaGeoJsonLayer/type.ts +108 -0
- package/src/core/CesiumAlphaViewer/index.ts +106 -0
- package/src/core/CesiumAlphaViewer/method/clusterFun.ts +116 -0
- package/src/core/CesiumAlphaViewer/method/createViewer.ts +53 -0
- package/src/core/CesiumAlphaViewer/method/goTo.ts +108 -0
- package/src/core/CesiumAlphaViewer/method/load3DtilestModel.ts +56 -0
- package/src/core/CesiumAlphaViewer/method/loadGeoJsonLayer.ts +33 -0
- package/src/core/CesiumAlphaViewer/type.ts +141 -0
- package/src/index.ts +10 -0
- package/src/util/PrimitiveCuster/index.js +1000 -0
- package/src/util/getPositionCenters/getPositionCenter.ts +25 -0
- package/src/util/parseColor/index.ts +39 -0
- package/tsconfig.json +28 -0
- package/types/core/CesiumAlphaViewer/index.d.ts +7 -0
- package/types/core/CesiumAlphaViewer/method/createViewer.d.ts +3 -0
- package/types/core/CesiumAlphaViewer/method/goTo.d.ts +3 -0
- package/types/core/CesiumAlphaViewer/type.d.ts +77 -0
- package/types/index.d.ts +2 -0
- package/viewTest/App.vue +38 -0
- package/viewTest/main.ts +10 -0
- package/viewTest/style/style.scss +4 -0
- package/vite.config.ts +69 -0
|
@@ -0,0 +1,1000 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BoundingRectangle,
|
|
3
|
+
Cartesian2,
|
|
4
|
+
Cartesian3,
|
|
5
|
+
defaultValue,
|
|
6
|
+
defined,
|
|
7
|
+
EllipsoidalOccluder,
|
|
8
|
+
Event,
|
|
9
|
+
Matrix4,
|
|
10
|
+
Billboard,
|
|
11
|
+
BillboardCollection,
|
|
12
|
+
Label,
|
|
13
|
+
LabelCollection,
|
|
14
|
+
PointPrimitive,
|
|
15
|
+
PointPrimitiveCollection,
|
|
16
|
+
SceneMode,
|
|
17
|
+
} from "cesium";
|
|
18
|
+
import KDBush from "kdbush";
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Defines how screen space objects (billboards, points, labels) are clustered.
|
|
22
|
+
*
|
|
23
|
+
* @param {Object} [options] An object with the following properties:
|
|
24
|
+
* @param {Boolean} [options.enabled=false] Whether or not to enable clustering.
|
|
25
|
+
* @param {Number} [options.pixelRange=80] The pixel range to extend the screen space bounding box.
|
|
26
|
+
* @param {Number} [options.minimumClusterSize=2] The minimum number of screen space objects that can be clustered.
|
|
27
|
+
* @param {Boolean} [options.clusterBillboards=true] Whether or not to cluster the billboards of an entity.
|
|
28
|
+
* @param {Boolean} [options.clusterLabels=true] Whether or not to cluster the labels of an entity.
|
|
29
|
+
* @param {Boolean} [options.clusterPoints=true] Whether or not to cluster the points of an entity.
|
|
30
|
+
* @param {Boolean} [options.show=true] Determines if the entities in the cluster will be shown.
|
|
31
|
+
*
|
|
32
|
+
* @alias PrimitiveCluster
|
|
33
|
+
* @constructor
|
|
34
|
+
*
|
|
35
|
+
* @demo {@link https://sandcastle.cesium.com/index.html?src=Clustering.html|Cesium Sandcastle Clustering Demo}
|
|
36
|
+
*/
|
|
37
|
+
function PrimitiveCluster(options) {
|
|
38
|
+
options = defaultValue(options, defaultValue.EMPTY_OBJECT);
|
|
39
|
+
|
|
40
|
+
this._enabled = defaultValue(options.enabled, false);
|
|
41
|
+
this._pixelRange = defaultValue(options.pixelRange, 80);
|
|
42
|
+
this._minimumClusterSize = defaultValue(options.minimumClusterSize, 2);
|
|
43
|
+
this._clusterBillboards = defaultValue(options.clusterBillboards, true);
|
|
44
|
+
this._clusterLabels = defaultValue(options.clusterLabels, true);
|
|
45
|
+
this._clusterPoints = defaultValue(options.clusterPoints, true);
|
|
46
|
+
|
|
47
|
+
this._labelCollection = undefined;
|
|
48
|
+
this._billboardCollection = undefined;
|
|
49
|
+
this._pointCollection = undefined;
|
|
50
|
+
|
|
51
|
+
this._clusterBillboardCollection = undefined;
|
|
52
|
+
this._clusterLabelCollection = undefined;
|
|
53
|
+
this._clusterPointCollection = undefined;
|
|
54
|
+
|
|
55
|
+
this._collectionIndicesByEntity = {};
|
|
56
|
+
|
|
57
|
+
this._unusedLabelIndices = [];
|
|
58
|
+
this._unusedBillboardIndices = [];
|
|
59
|
+
this._unusedPointIndices = [];
|
|
60
|
+
|
|
61
|
+
this._previousClusters = [];
|
|
62
|
+
this._previousHeight = undefined;
|
|
63
|
+
|
|
64
|
+
this._enabledDirty = false;
|
|
65
|
+
this._clusterDirty = false;
|
|
66
|
+
|
|
67
|
+
this._cluster = undefined;
|
|
68
|
+
this._removeEventListener = undefined;
|
|
69
|
+
|
|
70
|
+
this._listenerFun=undefined
|
|
71
|
+
|
|
72
|
+
this._clusterEvent = new Event();
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Determines if entities in this collection will be shown.
|
|
76
|
+
*
|
|
77
|
+
* @type {Boolean}
|
|
78
|
+
* @default true
|
|
79
|
+
*/
|
|
80
|
+
this.show = defaultValue(options.show, true);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function getX(point) {
|
|
84
|
+
return point.coord.x;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function getY(point) {
|
|
88
|
+
return point.coord.y;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function expandBoundingBox(bbox, pixelRange) {
|
|
92
|
+
bbox.x -= pixelRange;
|
|
93
|
+
bbox.y -= pixelRange;
|
|
94
|
+
bbox.width += pixelRange * 2.0;
|
|
95
|
+
bbox.height += pixelRange * 2.0;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const labelBoundingBoxScratch = new BoundingRectangle();
|
|
99
|
+
|
|
100
|
+
function getBoundingBox(item, coord, pixelRange, entityCluster, result) {
|
|
101
|
+
if (defined(item._labelCollection) && entityCluster._clusterLabels) {
|
|
102
|
+
result = Label.getScreenSpaceBoundingBox(item, coord, result);
|
|
103
|
+
} else if (
|
|
104
|
+
defined(item._billboardCollection) &&
|
|
105
|
+
entityCluster._clusterBillboards
|
|
106
|
+
) {
|
|
107
|
+
result = Billboard.getScreenSpaceBoundingBox(item, coord, result);
|
|
108
|
+
} else if (
|
|
109
|
+
defined(item._pointPrimitiveCollection) &&
|
|
110
|
+
entityCluster._clusterPoints
|
|
111
|
+
) {
|
|
112
|
+
result = PointPrimitive.getScreenSpaceBoundingBox(item, coord, result);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
expandBoundingBox(result, pixelRange);
|
|
116
|
+
|
|
117
|
+
if (
|
|
118
|
+
entityCluster._clusterLabels &&
|
|
119
|
+
!defined(item._labelCollection) &&
|
|
120
|
+
defined(item.id) &&
|
|
121
|
+
hasLabelIndex(entityCluster, item.id.id) &&
|
|
122
|
+
defined(item.id._label)
|
|
123
|
+
) {
|
|
124
|
+
const labelIndex =
|
|
125
|
+
entityCluster._collectionIndicesByEntity[item.id.id].labelIndex;
|
|
126
|
+
const label = entityCluster._labelCollection.get(labelIndex);
|
|
127
|
+
const labelBBox = Label.getScreenSpaceBoundingBox(
|
|
128
|
+
label,
|
|
129
|
+
coord,
|
|
130
|
+
labelBoundingBoxScratch
|
|
131
|
+
);
|
|
132
|
+
expandBoundingBox(labelBBox, pixelRange);
|
|
133
|
+
result = BoundingRectangle.union(result, labelBBox, result);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return result;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function addNonClusteredItem(item, entityCluster) {
|
|
140
|
+
item.clusterShow = true;
|
|
141
|
+
|
|
142
|
+
if (
|
|
143
|
+
!defined(item._labelCollection) &&
|
|
144
|
+
defined(item.id) &&
|
|
145
|
+
hasLabelIndex(entityCluster, item.id.id) &&
|
|
146
|
+
defined(item.id._label)
|
|
147
|
+
) {
|
|
148
|
+
const labelIndex =
|
|
149
|
+
entityCluster._collectionIndicesByEntity[item.id.id].labelIndex;
|
|
150
|
+
const label = entityCluster._labelCollection.get(labelIndex);
|
|
151
|
+
label.clusterShow = true;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function addCluster(position, numPoints, ids, entityCluster) {
|
|
156
|
+
const cluster = {
|
|
157
|
+
billboard: entityCluster._clusterBillboardCollection.add(),
|
|
158
|
+
label: entityCluster._clusterLabelCollection.add(),
|
|
159
|
+
point: entityCluster._clusterPointCollection.add(),
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
cluster.billboard.show = false;
|
|
163
|
+
cluster.point.show = false;
|
|
164
|
+
cluster.label.show = true;
|
|
165
|
+
cluster.label.text = numPoints.toLocaleString();
|
|
166
|
+
cluster.label.id = ids;
|
|
167
|
+
cluster.billboard.position = cluster.label.position = cluster.point.position = position;
|
|
168
|
+
|
|
169
|
+
entityCluster._clusterEvent.raiseEvent(ids, cluster);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function hasLabelIndex(entityCluster, entityId) {
|
|
173
|
+
return (
|
|
174
|
+
defined(entityCluster) &&
|
|
175
|
+
defined(entityCluster._collectionIndicesByEntity[entityId]) &&
|
|
176
|
+
defined(entityCluster._collectionIndicesByEntity[entityId].labelIndex)
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function getScreenSpacePositions(
|
|
181
|
+
collection,
|
|
182
|
+
points,
|
|
183
|
+
scene,
|
|
184
|
+
occluder,
|
|
185
|
+
entityCluster
|
|
186
|
+
) {
|
|
187
|
+
if (!defined(collection)) {
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const length = collection.length;
|
|
192
|
+
for (let i = 0; i < length; ++i) {
|
|
193
|
+
const item = collection.get(i);
|
|
194
|
+
item.clusterShow = false;
|
|
195
|
+
|
|
196
|
+
if (
|
|
197
|
+
!item.show ||
|
|
198
|
+
(entityCluster._scene.mode === SceneMode.SCENE3D &&
|
|
199
|
+
!occluder.isPointVisible(item.position))
|
|
200
|
+
) {
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// const canClusterLabels =
|
|
205
|
+
// entityCluster._clusterLabels && defined(item._labelCollection);
|
|
206
|
+
// const canClusterBillboards =
|
|
207
|
+
// entityCluster._clusterBillboards && defined(item.id._billboard);
|
|
208
|
+
// const canClusterPoints =
|
|
209
|
+
// entityCluster._clusterPoints && defined(item.id._point);
|
|
210
|
+
// if (canClusterLabels && (canClusterPoints || canClusterBillboards)) {
|
|
211
|
+
// continue;
|
|
212
|
+
// }
|
|
213
|
+
|
|
214
|
+
const coord = item.computeScreenSpacePosition(scene);
|
|
215
|
+
if (!defined(coord)) {
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
points.push({
|
|
220
|
+
index: i,
|
|
221
|
+
collection: collection,
|
|
222
|
+
clustered: false,
|
|
223
|
+
coord: coord,
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const pointBoundinRectangleScratch = new BoundingRectangle();
|
|
229
|
+
const totalBoundingRectangleScratch = new BoundingRectangle();
|
|
230
|
+
const neighborBoundingRectangleScratch = new BoundingRectangle();
|
|
231
|
+
|
|
232
|
+
function createDeclutterCallback(entityCluster) {
|
|
233
|
+
return function (amount) {
|
|
234
|
+
if ((defined(amount) && amount < 0.05) || !entityCluster.enabled) {
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const scene = entityCluster._scene;
|
|
239
|
+
|
|
240
|
+
const labelCollection = entityCluster._labelCollection;
|
|
241
|
+
const billboardCollection = entityCluster._billboardCollection;
|
|
242
|
+
const pointCollection = entityCluster._pointCollection;
|
|
243
|
+
|
|
244
|
+
if (
|
|
245
|
+
(!defined(labelCollection) &&
|
|
246
|
+
!defined(billboardCollection) &&
|
|
247
|
+
!defined(pointCollection)) ||
|
|
248
|
+
(!entityCluster._clusterBillboards &&
|
|
249
|
+
!entityCluster._clusterLabels &&
|
|
250
|
+
!entityCluster._clusterPoints)
|
|
251
|
+
) {
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
let clusteredLabelCollection = entityCluster._clusterLabelCollection;
|
|
256
|
+
let clusteredBillboardCollection =
|
|
257
|
+
entityCluster._clusterBillboardCollection;
|
|
258
|
+
let clusteredPointCollection = entityCluster._clusterPointCollection;
|
|
259
|
+
|
|
260
|
+
if (defined(clusteredLabelCollection)) {
|
|
261
|
+
clusteredLabelCollection.removeAll();
|
|
262
|
+
} else {
|
|
263
|
+
clusteredLabelCollection = entityCluster._clusterLabelCollection = new LabelCollection(
|
|
264
|
+
{
|
|
265
|
+
scene: scene,
|
|
266
|
+
}
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
if (defined(clusteredBillboardCollection)) {
|
|
271
|
+
clusteredBillboardCollection.removeAll();
|
|
272
|
+
} else {
|
|
273
|
+
clusteredBillboardCollection = entityCluster._clusterBillboardCollection = new BillboardCollection(
|
|
274
|
+
{
|
|
275
|
+
scene: scene,
|
|
276
|
+
}
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
if (defined(clusteredPointCollection)) {
|
|
281
|
+
clusteredPointCollection.removeAll();
|
|
282
|
+
} else {
|
|
283
|
+
clusteredPointCollection = entityCluster._clusterPointCollection = new PointPrimitiveCollection();
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
const pixelRange = entityCluster._pixelRange;
|
|
287
|
+
const minimumClusterSize = entityCluster._minimumClusterSize;
|
|
288
|
+
|
|
289
|
+
const clusters = entityCluster._previousClusters;
|
|
290
|
+
const newClusters = [];
|
|
291
|
+
|
|
292
|
+
const previousHeight = entityCluster._previousHeight;
|
|
293
|
+
const currentHeight = scene.camera.positionCartographic.height;
|
|
294
|
+
|
|
295
|
+
const ellipsoid = scene.mapProjection.ellipsoid;
|
|
296
|
+
const cameraPosition = scene.camera.positionWC;
|
|
297
|
+
const occluder = new EllipsoidalOccluder(ellipsoid, cameraPosition);
|
|
298
|
+
|
|
299
|
+
const points = [];
|
|
300
|
+
if (entityCluster._clusterLabels) {
|
|
301
|
+
getScreenSpacePositions(
|
|
302
|
+
labelCollection,
|
|
303
|
+
points,
|
|
304
|
+
scene,
|
|
305
|
+
occluder,
|
|
306
|
+
entityCluster
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
if (entityCluster._clusterBillboards) {
|
|
310
|
+
getScreenSpacePositions(
|
|
311
|
+
billboardCollection,
|
|
312
|
+
points,
|
|
313
|
+
scene,
|
|
314
|
+
occluder,
|
|
315
|
+
entityCluster
|
|
316
|
+
);
|
|
317
|
+
}
|
|
318
|
+
if (entityCluster._clusterPoints) {
|
|
319
|
+
getScreenSpacePositions(
|
|
320
|
+
pointCollection,
|
|
321
|
+
points,
|
|
322
|
+
scene,
|
|
323
|
+
occluder,
|
|
324
|
+
entityCluster
|
|
325
|
+
);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
let i;
|
|
329
|
+
let j;
|
|
330
|
+
let length;
|
|
331
|
+
let bbox;
|
|
332
|
+
let neighbors;
|
|
333
|
+
let neighborLength;
|
|
334
|
+
let neighborIndex;
|
|
335
|
+
let neighborPoint;
|
|
336
|
+
let ids;
|
|
337
|
+
let numPoints;
|
|
338
|
+
|
|
339
|
+
let collection;
|
|
340
|
+
let collectionIndex;
|
|
341
|
+
|
|
342
|
+
const index = new KDBush(points, getX, getY, 64, Int32Array);
|
|
343
|
+
|
|
344
|
+
if (currentHeight < previousHeight) {
|
|
345
|
+
length = clusters.length;
|
|
346
|
+
for (i = 0; i < length; ++i) {
|
|
347
|
+
const cluster = clusters[i];
|
|
348
|
+
|
|
349
|
+
if (!occluder.isPointVisible(cluster.position)) {
|
|
350
|
+
continue;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
const coord = Billboard._computeScreenSpacePosition(
|
|
354
|
+
Matrix4.IDENTITY,
|
|
355
|
+
cluster.position,
|
|
356
|
+
Cartesian3.ZERO,
|
|
357
|
+
Cartesian2.ZERO,
|
|
358
|
+
scene
|
|
359
|
+
);
|
|
360
|
+
if (!defined(coord)) {
|
|
361
|
+
continue;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
const factor = 1.0 - currentHeight / previousHeight;
|
|
365
|
+
let width = (cluster.width = cluster.width * factor);
|
|
366
|
+
let height = (cluster.height = cluster.height * factor);
|
|
367
|
+
|
|
368
|
+
width = Math.max(width, cluster.minimumWidth);
|
|
369
|
+
height = Math.max(height, cluster.minimumHeight);
|
|
370
|
+
|
|
371
|
+
const minX = coord.x - width * 0.5;
|
|
372
|
+
const minY = coord.y - height * 0.5;
|
|
373
|
+
const maxX = coord.x + width;
|
|
374
|
+
const maxY = coord.y + height;
|
|
375
|
+
|
|
376
|
+
neighbors = index.range(minX, minY, maxX, maxY);
|
|
377
|
+
neighborLength = neighbors.length;
|
|
378
|
+
numPoints = 0;
|
|
379
|
+
ids = [];
|
|
380
|
+
|
|
381
|
+
for (j = 0; j < neighborLength; ++j) {
|
|
382
|
+
neighborIndex = neighbors[j];
|
|
383
|
+
neighborPoint = points[neighborIndex];
|
|
384
|
+
if (!neighborPoint.clustered) {
|
|
385
|
+
++numPoints;
|
|
386
|
+
|
|
387
|
+
collection = neighborPoint.collection;
|
|
388
|
+
collectionIndex = neighborPoint.index;
|
|
389
|
+
ids.push(collection.get(collectionIndex).id);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
if (numPoints >= minimumClusterSize) {
|
|
394
|
+
addCluster(cluster.position, numPoints, ids, entityCluster);
|
|
395
|
+
newClusters.push(cluster);
|
|
396
|
+
|
|
397
|
+
for (j = 0; j < neighborLength; ++j) {
|
|
398
|
+
points[neighbors[j]].clustered = true;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
length = points.length;
|
|
405
|
+
for (i = 0; i < length; ++i) {
|
|
406
|
+
const point = points[i];
|
|
407
|
+
if (point.clustered) {
|
|
408
|
+
continue;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
point.clustered = true;
|
|
412
|
+
|
|
413
|
+
collection = point.collection;
|
|
414
|
+
collectionIndex = point.index;
|
|
415
|
+
|
|
416
|
+
const item = collection.get(collectionIndex);
|
|
417
|
+
bbox = getBoundingBox(
|
|
418
|
+
item,
|
|
419
|
+
point.coord,
|
|
420
|
+
pixelRange,
|
|
421
|
+
entityCluster,
|
|
422
|
+
pointBoundinRectangleScratch
|
|
423
|
+
);
|
|
424
|
+
const totalBBox = BoundingRectangle.clone(
|
|
425
|
+
bbox,
|
|
426
|
+
totalBoundingRectangleScratch
|
|
427
|
+
);
|
|
428
|
+
|
|
429
|
+
neighbors = index.range(
|
|
430
|
+
bbox.x,
|
|
431
|
+
bbox.y,
|
|
432
|
+
bbox.x + bbox.width,
|
|
433
|
+
bbox.y + bbox.height
|
|
434
|
+
);
|
|
435
|
+
neighborLength = neighbors.length;
|
|
436
|
+
|
|
437
|
+
const clusterPosition = Cartesian3.clone(item.position);
|
|
438
|
+
numPoints = 1;
|
|
439
|
+
ids = [item.id];
|
|
440
|
+
|
|
441
|
+
for (j = 0; j < neighborLength; ++j) {
|
|
442
|
+
neighborIndex = neighbors[j];
|
|
443
|
+
neighborPoint = points[neighborIndex];
|
|
444
|
+
if (!neighborPoint.clustered) {
|
|
445
|
+
const neighborItem = neighborPoint.collection.get(
|
|
446
|
+
neighborPoint.index
|
|
447
|
+
);
|
|
448
|
+
const neighborBBox = getBoundingBox(
|
|
449
|
+
neighborItem,
|
|
450
|
+
neighborPoint.coord,
|
|
451
|
+
pixelRange,
|
|
452
|
+
entityCluster,
|
|
453
|
+
neighborBoundingRectangleScratch
|
|
454
|
+
);
|
|
455
|
+
|
|
456
|
+
Cartesian3.add(
|
|
457
|
+
neighborItem.position,
|
|
458
|
+
clusterPosition,
|
|
459
|
+
clusterPosition
|
|
460
|
+
);
|
|
461
|
+
|
|
462
|
+
BoundingRectangle.union(totalBBox, neighborBBox, totalBBox);
|
|
463
|
+
++numPoints;
|
|
464
|
+
|
|
465
|
+
ids.push(neighborItem.id);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
if (numPoints >= minimumClusterSize) {
|
|
470
|
+
const position = Cartesian3.multiplyByScalar(
|
|
471
|
+
clusterPosition,
|
|
472
|
+
1.0 / numPoints,
|
|
473
|
+
clusterPosition
|
|
474
|
+
);
|
|
475
|
+
addCluster(position, numPoints, ids, entityCluster);
|
|
476
|
+
newClusters.push({
|
|
477
|
+
position: position,
|
|
478
|
+
width: totalBBox.width,
|
|
479
|
+
height: totalBBox.height,
|
|
480
|
+
minimumWidth: bbox.width,
|
|
481
|
+
minimumHeight: bbox.height,
|
|
482
|
+
});
|
|
483
|
+
|
|
484
|
+
for (j = 0; j < neighborLength; ++j) {
|
|
485
|
+
points[neighbors[j]].clustered = true;
|
|
486
|
+
}
|
|
487
|
+
} else {
|
|
488
|
+
addNonClusteredItem(item, entityCluster);
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
if (clusteredLabelCollection.length === 0) {
|
|
493
|
+
clusteredLabelCollection.destroy();
|
|
494
|
+
entityCluster._clusterLabelCollection = undefined;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
if (clusteredBillboardCollection.length === 0) {
|
|
498
|
+
clusteredBillboardCollection.destroy();
|
|
499
|
+
entityCluster._clusterBillboardCollection = undefined;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
if (clusteredPointCollection.length === 0) {
|
|
503
|
+
clusteredPointCollection.destroy();
|
|
504
|
+
entityCluster._clusterPointCollection = undefined;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
entityCluster._previousClusters = newClusters;
|
|
508
|
+
entityCluster._previousHeight = currentHeight;
|
|
509
|
+
};
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
PrimitiveCluster.prototype._initialize = function (scene) {
|
|
513
|
+
this._scene = scene;
|
|
514
|
+
|
|
515
|
+
const cluster = createDeclutterCallback(this);
|
|
516
|
+
this._cluster = cluster;
|
|
517
|
+
this._removeEventListener = scene.camera.changed.addEventListener(cluster);
|
|
518
|
+
};
|
|
519
|
+
|
|
520
|
+
Object.defineProperties(PrimitiveCluster.prototype, {
|
|
521
|
+
/**
|
|
522
|
+
* Gets or sets whether clustering is enabled.
|
|
523
|
+
* @memberof PrimitiveCluster.prototype
|
|
524
|
+
* @type {Boolean}
|
|
525
|
+
*/
|
|
526
|
+
enabled: {
|
|
527
|
+
get: function () {
|
|
528
|
+
return this._enabled;
|
|
529
|
+
},
|
|
530
|
+
set: function (value) {
|
|
531
|
+
this._enabledDirty = value !== this._enabled;
|
|
532
|
+
this._enabled = value;
|
|
533
|
+
},
|
|
534
|
+
},
|
|
535
|
+
/**
|
|
536
|
+
* Gets or sets the pixel range to extend the screen space bounding box.
|
|
537
|
+
* @memberof PrimitiveCluster.prototype
|
|
538
|
+
* @type {Number}
|
|
539
|
+
*/
|
|
540
|
+
pixelRange: {
|
|
541
|
+
get: function () {
|
|
542
|
+
return this._pixelRange;
|
|
543
|
+
},
|
|
544
|
+
set: function (value) {
|
|
545
|
+
this._clusterDirty = this._clusterDirty || value !== this._pixelRange;
|
|
546
|
+
this._pixelRange = value;
|
|
547
|
+
},
|
|
548
|
+
},
|
|
549
|
+
/**
|
|
550
|
+
* Gets or sets the minimum number of screen space objects that can be clustered.
|
|
551
|
+
* @memberof PrimitiveCluster.prototype
|
|
552
|
+
* @type {Number}
|
|
553
|
+
*/
|
|
554
|
+
minimumClusterSize: {
|
|
555
|
+
get: function () {
|
|
556
|
+
return this._minimumClusterSize;
|
|
557
|
+
},
|
|
558
|
+
set: function (value) {
|
|
559
|
+
this._clusterDirty =
|
|
560
|
+
this._clusterDirty || value !== this._minimumClusterSize;
|
|
561
|
+
this._minimumClusterSize = value;
|
|
562
|
+
},
|
|
563
|
+
},
|
|
564
|
+
/**
|
|
565
|
+
* Gets the event that will be raised when a new cluster will be displayed. The signature of the event listener is {@link PrimitiveCluster.newClusterCallback}.
|
|
566
|
+
* @memberof PrimitiveCluster.prototype
|
|
567
|
+
* @type {Event<PrimitiveCluster.newClusterCallback>}
|
|
568
|
+
*/
|
|
569
|
+
clusterEvent: {
|
|
570
|
+
get: function () {
|
|
571
|
+
return this._clusterEvent;
|
|
572
|
+
},
|
|
573
|
+
},
|
|
574
|
+
/**
|
|
575
|
+
* Gets or sets whether clustering billboard entities is enabled.
|
|
576
|
+
* @memberof PrimitiveCluster.prototype
|
|
577
|
+
* @type {Boolean}
|
|
578
|
+
*/
|
|
579
|
+
clusterBillboards: {
|
|
580
|
+
get: function () {
|
|
581
|
+
return this._clusterBillboards;
|
|
582
|
+
},
|
|
583
|
+
set: function (value) {
|
|
584
|
+
this._clusterDirty =
|
|
585
|
+
this._clusterDirty || value !== this._clusterBillboards;
|
|
586
|
+
this._clusterBillboards = value;
|
|
587
|
+
},
|
|
588
|
+
},
|
|
589
|
+
/**
|
|
590
|
+
* Gets or sets whether clustering labels entities is enabled.
|
|
591
|
+
* @memberof PrimitiveCluster.prototype
|
|
592
|
+
* @type {Boolean}
|
|
593
|
+
*/
|
|
594
|
+
clusterLabels: {
|
|
595
|
+
get: function () {
|
|
596
|
+
return this._clusterLabels;
|
|
597
|
+
},
|
|
598
|
+
set: function (value) {
|
|
599
|
+
this._clusterDirty = this._clusterDirty || value !== this._clusterLabels;
|
|
600
|
+
this._clusterLabels = value;
|
|
601
|
+
},
|
|
602
|
+
},
|
|
603
|
+
/**
|
|
604
|
+
* Gets or sets whether clustering point entities is enabled.
|
|
605
|
+
* @memberof PrimitiveCluster.prototype
|
|
606
|
+
* @type {Boolean}
|
|
607
|
+
*/
|
|
608
|
+
clusterPoints: {
|
|
609
|
+
get: function () {
|
|
610
|
+
return this._clusterPoints;
|
|
611
|
+
},
|
|
612
|
+
set: function (value) {
|
|
613
|
+
this._clusterDirty = this._clusterDirty || value !== this._clusterPoints;
|
|
614
|
+
this._clusterPoints = value;
|
|
615
|
+
},
|
|
616
|
+
},
|
|
617
|
+
});
|
|
618
|
+
|
|
619
|
+
function createGetEntity(
|
|
620
|
+
collectionProperty,
|
|
621
|
+
CollectionConstructor,
|
|
622
|
+
unusedIndicesProperty,
|
|
623
|
+
entityIndexProperty
|
|
624
|
+
) {
|
|
625
|
+
return function (entity) {
|
|
626
|
+
let collection = this[collectionProperty];
|
|
627
|
+
|
|
628
|
+
if (!defined(this._collectionIndicesByEntity)) {
|
|
629
|
+
this._collectionIndicesByEntity = {};
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
let entityIndices = this._collectionIndicesByEntity[entity.id];
|
|
633
|
+
|
|
634
|
+
if (!defined(entityIndices)) {
|
|
635
|
+
entityIndices = this._collectionIndicesByEntity[entity.id] = {
|
|
636
|
+
billboardIndex: undefined,
|
|
637
|
+
labelIndex: undefined,
|
|
638
|
+
pointIndex: undefined,
|
|
639
|
+
};
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
if (defined(collection) && defined(entityIndices[entityIndexProperty])) {
|
|
643
|
+
return collection.get(entityIndices[entityIndexProperty]);
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
if (!defined(collection)) {
|
|
647
|
+
collection = this[collectionProperty] = new CollectionConstructor({
|
|
648
|
+
scene: this._scene,
|
|
649
|
+
});
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
let index;
|
|
653
|
+
let entityItem;
|
|
654
|
+
|
|
655
|
+
const unusedIndices = this[unusedIndicesProperty];
|
|
656
|
+
if (unusedIndices.length > 0) {
|
|
657
|
+
index = unusedIndices.pop();
|
|
658
|
+
entityItem = collection.get(index);
|
|
659
|
+
} else {
|
|
660
|
+
entityItem = collection.add();
|
|
661
|
+
index = collection.length - 1;
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
entityIndices[entityIndexProperty] = index;
|
|
665
|
+
|
|
666
|
+
const that = this;
|
|
667
|
+
Promise.resolve().then(function () {
|
|
668
|
+
that._clusterDirty = true;
|
|
669
|
+
});
|
|
670
|
+
|
|
671
|
+
return entityItem;
|
|
672
|
+
};
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
function removeEntityIndicesIfUnused(entityCluster, entityId) {
|
|
676
|
+
const indices = entityCluster._collectionIndicesByEntity[entityId];
|
|
677
|
+
|
|
678
|
+
if (
|
|
679
|
+
!defined(indices.billboardIndex) &&
|
|
680
|
+
!defined(indices.labelIndex) &&
|
|
681
|
+
!defined(indices.pointIndex)
|
|
682
|
+
) {
|
|
683
|
+
delete entityCluster._collectionIndicesByEntity[entityId];
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
/**
|
|
688
|
+
* Returns a new {@link Label}.
|
|
689
|
+
* @param {Entity} entity The entity that will use the returned {@link Label} for visualization.
|
|
690
|
+
* @returns {Label} The label that will be used to visualize an entity.
|
|
691
|
+
*
|
|
692
|
+
* @private
|
|
693
|
+
*/
|
|
694
|
+
PrimitiveCluster.prototype.getLabel = createGetEntity(
|
|
695
|
+
"_labelCollection",
|
|
696
|
+
LabelCollection,
|
|
697
|
+
"_unusedLabelIndices",
|
|
698
|
+
"labelIndex"
|
|
699
|
+
);
|
|
700
|
+
|
|
701
|
+
/**
|
|
702
|
+
* Removes the {@link Label} associated with an entity so it can be reused by another entity.
|
|
703
|
+
* @param {Entity} entity The entity that will uses the returned {@link Label} for visualization.
|
|
704
|
+
*
|
|
705
|
+
* @private
|
|
706
|
+
*/
|
|
707
|
+
PrimitiveCluster.prototype.removeLabel = function (entity) {
|
|
708
|
+
const entityIndices =
|
|
709
|
+
this._collectionIndicesByEntity &&
|
|
710
|
+
this._collectionIndicesByEntity[entity.id];
|
|
711
|
+
if (
|
|
712
|
+
!defined(this._labelCollection) ||
|
|
713
|
+
!defined(entityIndices) ||
|
|
714
|
+
!defined(entityIndices.labelIndex)
|
|
715
|
+
) {
|
|
716
|
+
return;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
const index = entityIndices.labelIndex;
|
|
720
|
+
entityIndices.labelIndex = undefined;
|
|
721
|
+
removeEntityIndicesIfUnused(this, entity.id);
|
|
722
|
+
|
|
723
|
+
const label = this._labelCollection.get(index);
|
|
724
|
+
label.show = false;
|
|
725
|
+
label.text = "";
|
|
726
|
+
label.id = undefined;
|
|
727
|
+
|
|
728
|
+
this._unusedLabelIndices.push(index);
|
|
729
|
+
|
|
730
|
+
this._clusterDirty = true;
|
|
731
|
+
};
|
|
732
|
+
|
|
733
|
+
/**
|
|
734
|
+
* Returns a new {@link Billboard}.
|
|
735
|
+
* @param {Entity} entity The entity that will use the returned {@link Billboard} for visualization.
|
|
736
|
+
* @returns {Billboard} The label that will be used to visualize an entity.
|
|
737
|
+
*
|
|
738
|
+
* @private
|
|
739
|
+
*/
|
|
740
|
+
PrimitiveCluster.prototype.getBillboard = createGetEntity(
|
|
741
|
+
"_billboardCollection",
|
|
742
|
+
BillboardCollection,
|
|
743
|
+
"_unusedBillboardIndices",
|
|
744
|
+
"billboardIndex"
|
|
745
|
+
);
|
|
746
|
+
|
|
747
|
+
/**
|
|
748
|
+
* Removes the {@link Billboard} associated with an entity so it can be reused by another entity.
|
|
749
|
+
* @param {Entity} entity The entity that will uses the returned {@link Billboard} for visualization.
|
|
750
|
+
*
|
|
751
|
+
* @private
|
|
752
|
+
*/
|
|
753
|
+
PrimitiveCluster.prototype.removeBillboard = function (entity) {
|
|
754
|
+
const entityIndices =
|
|
755
|
+
this._collectionIndicesByEntity &&
|
|
756
|
+
this._collectionIndicesByEntity[entity.id];
|
|
757
|
+
if (
|
|
758
|
+
!defined(this._billboardCollection) ||
|
|
759
|
+
!defined(entityIndices) ||
|
|
760
|
+
!defined(entityIndices.billboardIndex)
|
|
761
|
+
) {
|
|
762
|
+
return;
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
const index = entityIndices.billboardIndex;
|
|
766
|
+
entityIndices.billboardIndex = undefined;
|
|
767
|
+
removeEntityIndicesIfUnused(this, entity.id);
|
|
768
|
+
|
|
769
|
+
const billboard = this._billboardCollection.get(index);
|
|
770
|
+
billboard.id = undefined;
|
|
771
|
+
billboard.show = false;
|
|
772
|
+
billboard.image = undefined;
|
|
773
|
+
|
|
774
|
+
this._unusedBillboardIndices.push(index);
|
|
775
|
+
|
|
776
|
+
this._clusterDirty = true;
|
|
777
|
+
};
|
|
778
|
+
|
|
779
|
+
/**
|
|
780
|
+
* Returns a new {@link Point}.
|
|
781
|
+
* @param {Entity} entity The entity that will use the returned {@link Point} for visualization.
|
|
782
|
+
* @returns {Point} The label that will be used to visualize an entity.
|
|
783
|
+
*
|
|
784
|
+
* @private
|
|
785
|
+
*/
|
|
786
|
+
PrimitiveCluster.prototype.getPoint = createGetEntity(
|
|
787
|
+
"_pointCollection",
|
|
788
|
+
PointPrimitiveCollection,
|
|
789
|
+
"_unusedPointIndices",
|
|
790
|
+
"pointIndex"
|
|
791
|
+
);
|
|
792
|
+
|
|
793
|
+
/**
|
|
794
|
+
* Removes the {@link Point} associated with an entity so it can be reused by another entity.
|
|
795
|
+
* @param {Entity} entity The entity that will uses the returned {@link Point} for visualization.
|
|
796
|
+
*
|
|
797
|
+
* @private
|
|
798
|
+
*/
|
|
799
|
+
PrimitiveCluster.prototype.removePoint = function (entity) {
|
|
800
|
+
const entityIndices =
|
|
801
|
+
this._collectionIndicesByEntity &&
|
|
802
|
+
this._collectionIndicesByEntity[entity.id];
|
|
803
|
+
if (
|
|
804
|
+
!defined(this._pointCollection) ||
|
|
805
|
+
!defined(entityIndices) ||
|
|
806
|
+
!defined(entityIndices.pointIndex)
|
|
807
|
+
) {
|
|
808
|
+
return;
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
const index = entityIndices.pointIndex;
|
|
812
|
+
entityIndices.pointIndex = undefined;
|
|
813
|
+
removeEntityIndicesIfUnused(this, entity.id);
|
|
814
|
+
|
|
815
|
+
const point = this._pointCollection.get(index);
|
|
816
|
+
point.show = false;
|
|
817
|
+
point.id = undefined;
|
|
818
|
+
|
|
819
|
+
this._unusedPointIndices.push(index);
|
|
820
|
+
|
|
821
|
+
this._clusterDirty = true;
|
|
822
|
+
};
|
|
823
|
+
|
|
824
|
+
function disableCollectionClustering(collection) {
|
|
825
|
+
if (!defined(collection)) {
|
|
826
|
+
return;
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
const length = collection.length;
|
|
830
|
+
for (let i = 0; i < length; ++i) {
|
|
831
|
+
collection.get(i).clusterShow = true;
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
function updateEnable(entityCluster) {
|
|
836
|
+
if (entityCluster.enabled) {
|
|
837
|
+
return;
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
if (defined(entityCluster._clusterLabelCollection)) {
|
|
841
|
+
entityCluster._clusterLabelCollection.destroy();
|
|
842
|
+
}
|
|
843
|
+
if (defined(entityCluster._clusterBillboardCollection)) {
|
|
844
|
+
entityCluster._clusterBillboardCollection.destroy();
|
|
845
|
+
}
|
|
846
|
+
if (defined(entityCluster._clusterPointCollection)) {
|
|
847
|
+
entityCluster._clusterPointCollection.destroy();
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
entityCluster._clusterLabelCollection = undefined;
|
|
851
|
+
entityCluster._clusterBillboardCollection = undefined;
|
|
852
|
+
entityCluster._clusterPointCollection = undefined;
|
|
853
|
+
|
|
854
|
+
disableCollectionClustering(entityCluster._labelCollection);
|
|
855
|
+
disableCollectionClustering(entityCluster._billboardCollection);
|
|
856
|
+
disableCollectionClustering(entityCluster._pointCollection);
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
/**
|
|
860
|
+
* Gets the draw commands for the clustered billboards/points/labels if enabled, otherwise,
|
|
861
|
+
* queues the draw commands for billboards/points/labels created for entities.
|
|
862
|
+
* @private
|
|
863
|
+
*/
|
|
864
|
+
PrimitiveCluster.prototype.update = function (frameState) {
|
|
865
|
+
if (!this.show) {
|
|
866
|
+
return;
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
// If clustering is enabled before the label collection is updated,
|
|
870
|
+
// the glyphs haven't been created so the screen space bounding boxes
|
|
871
|
+
// are incorrect.
|
|
872
|
+
let commandList;
|
|
873
|
+
if (
|
|
874
|
+
defined(this._labelCollection) &&
|
|
875
|
+
this._labelCollection.length > 0 &&
|
|
876
|
+
this._labelCollection.get(0)._glyphs.length === 0
|
|
877
|
+
) {
|
|
878
|
+
commandList = frameState.commandList;
|
|
879
|
+
frameState.commandList = [];
|
|
880
|
+
this._labelCollection.update(frameState);
|
|
881
|
+
frameState.commandList = commandList;
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
// If clustering is enabled before the billboard collection is updated,
|
|
885
|
+
// the images haven't been added to the image atlas so the screen space bounding boxes
|
|
886
|
+
// are incorrect.
|
|
887
|
+
if (
|
|
888
|
+
defined(this._billboardCollection) &&
|
|
889
|
+
this._billboardCollection.length > 0 &&
|
|
890
|
+
!defined(this._billboardCollection.get(0).width)
|
|
891
|
+
) {
|
|
892
|
+
commandList = frameState.commandList;
|
|
893
|
+
frameState.commandList = [];
|
|
894
|
+
this._billboardCollection.update(frameState);
|
|
895
|
+
frameState.commandList = commandList;
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
if (this._enabledDirty) {
|
|
899
|
+
this._enabledDirty = false;
|
|
900
|
+
updateEnable(this);
|
|
901
|
+
this._clusterDirty = true;
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
if (this._clusterDirty) {
|
|
905
|
+
this._clusterDirty = false;
|
|
906
|
+
this._cluster();
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
if (defined(this._clusterLabelCollection)) {
|
|
910
|
+
this._clusterLabelCollection.update(frameState);
|
|
911
|
+
}
|
|
912
|
+
if (defined(this._clusterBillboardCollection)) {
|
|
913
|
+
this._clusterBillboardCollection.update(frameState);
|
|
914
|
+
}
|
|
915
|
+
if (defined(this._clusterPointCollection)) {
|
|
916
|
+
this._clusterPointCollection.update(frameState);
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
if (defined(this._labelCollection)) {
|
|
920
|
+
this._labelCollection.update(frameState);
|
|
921
|
+
}
|
|
922
|
+
if (defined(this._billboardCollection)) {
|
|
923
|
+
this._billboardCollection.update(frameState);
|
|
924
|
+
}
|
|
925
|
+
if (defined(this._pointCollection)) {
|
|
926
|
+
this._pointCollection.update(frameState);
|
|
927
|
+
}
|
|
928
|
+
};
|
|
929
|
+
|
|
930
|
+
/**
|
|
931
|
+
* Destroys the WebGL resources held by this object. Destroying an object allows for deterministic
|
|
932
|
+
* release of WebGL resources, instead of relying on the garbage collector to destroy this object.
|
|
933
|
+
* <p>
|
|
934
|
+
* Unlike other objects that use WebGL resources, this object can be reused. For example, if a data source is removed
|
|
935
|
+
* from a data source collection and added to another.
|
|
936
|
+
* </p>
|
|
937
|
+
*/
|
|
938
|
+
PrimitiveCluster.prototype.destroy = function () {
|
|
939
|
+
this._labelCollection =
|
|
940
|
+
this._labelCollection && this._labelCollection.removeAll();
|
|
941
|
+
this._billboardCollection =
|
|
942
|
+
this._billboardCollection && this._billboardCollection.removeAll();
|
|
943
|
+
this._pointCollection =
|
|
944
|
+
this._pointCollection && this._pointCollection.removeAll();
|
|
945
|
+
this._clusterLabelCollection =
|
|
946
|
+
this._clusterLabelCollection && this._clusterLabelCollection.removeAll();
|
|
947
|
+
this._clusterBillboardCollection =
|
|
948
|
+
this._clusterBillboardCollection &&
|
|
949
|
+
this._clusterBillboardCollection.removeAll();
|
|
950
|
+
this._clusterPointCollection =
|
|
951
|
+
this._clusterPointCollection && this._clusterPointCollection.removeAll();
|
|
952
|
+
|
|
953
|
+
if (defined(this._removeEventListener)) {
|
|
954
|
+
this._removeEventListener();
|
|
955
|
+
this._removeEventListener = undefined;
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
this._labelCollection = undefined;
|
|
959
|
+
this._billboardCollection = undefined;
|
|
960
|
+
this._pointCollection = undefined;
|
|
961
|
+
|
|
962
|
+
this._clusterBillboardCollection = undefined;
|
|
963
|
+
this._clusterLabelCollection = undefined;
|
|
964
|
+
this._clusterPointCollection = undefined;
|
|
965
|
+
|
|
966
|
+
this._collectionIndicesByEntity = undefined;
|
|
967
|
+
|
|
968
|
+
this._unusedLabelIndices = [];
|
|
969
|
+
this._unusedBillboardIndices = [];
|
|
970
|
+
this._unusedPointIndices = [];
|
|
971
|
+
|
|
972
|
+
this._previousClusters = [];
|
|
973
|
+
this._previousHeight = undefined;
|
|
974
|
+
|
|
975
|
+
this._enabledDirty = false;
|
|
976
|
+
this._pixelRangeDirty = false;
|
|
977
|
+
this._minimumClusterSizeDirty = false;
|
|
978
|
+
|
|
979
|
+
return undefined;
|
|
980
|
+
};
|
|
981
|
+
|
|
982
|
+
/**
|
|
983
|
+
* A event listener function used to style clusters.
|
|
984
|
+
* @callback PrimitiveCluster.newClusterCallback
|
|
985
|
+
*
|
|
986
|
+
* @param {Entity[]} clusteredEntities An array of the entities contained in the cluster.
|
|
987
|
+
* @param {Object} cluster An object containing the Billboard, Label, and Point
|
|
988
|
+
* primitives that represent this cluster of entities.
|
|
989
|
+
* @param {Billboard} cluster.billboard
|
|
990
|
+
* @param {Label} cluster.label
|
|
991
|
+
* @param {PointPrimitive} cluster.point
|
|
992
|
+
*
|
|
993
|
+
* @example
|
|
994
|
+
* // The default cluster values.
|
|
995
|
+
* dataSource.clustering.clusterEvent.addEventListener(function(entities, cluster) {
|
|
996
|
+
* cluster.label.show = true;
|
|
997
|
+
* cluster.label.text = entities.length.toLocaleString();
|
|
998
|
+
* });
|
|
999
|
+
*/
|
|
1000
|
+
export default PrimitiveCluster;
|