EntityCluster BUG
When I use the EntityCluster of dataSource, using the following code and only replacing the version number will yield different results. The aggregation of the new version will directly return a single entity in the part outside the window. When dragging the camera, you will see a part of the single entity, which disappears after the aggregation starts. The effect is more pronounced in 2D view
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/dhs.jpeg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="/Cesium-1.135/Build/Cesium/Widgets/widgets.css" />
<script type="text/javascript" src="/Cesium-1.135/Build/Cesium/Cesium.js"></script>
</head>
<body style="margin: 0; overflow: hidden; background: #fff; width: 100%; height: 100%; position: absolute; top: 0">
<div id="map" style="margin: 0 auto; width: 100%; height: 100%"></div>
<!-- ./video.mp4 -->
<script type="text/javascript">
const viewer = new Cesium.Viewer('map', {});
viewer.scene.debugShowFramesPerSecond = true;
class pointCluster {
constructor(opt) {
this.options = {
dataOrUrl: '',
pixelRange: 15,
enabled: true,
colorArr: [
{
num: 1,
size: 48,
color: '#e6a23cbb',
},
],
img: '',
};
this.options = Object.assign(this.options, opt);
this.viewer = opt.viewer;
this.dataSources = null;
this.clustericon = {};
if (this.options.dataOrUrl && this.options.dataOrUrl != '') {
this.loadjson();
}
}
loadjson() {
var this_ = this;
new Cesium.GeoJsonDataSource().load(this_.options.dataOrUrl).then((geoJsonDataSource) => {
this_.showcluster(geoJsonDataSource);
});
}
showcluster(geoJsonDataSource) {
var this_ = this;
this.dataSources = geoJsonDataSource;
this.viewer.dataSources.add(this.dataSources);
var pixelRange = this.options.pixelRange;
var minimumClusterSize = 1;
var enabled = this.options.enabled;
//开启聚合
this.dataSources.clustering.enabled = enabled;
this.dataSources.clustering.pixelRange = pixelRange;
this.dataSources.clustering.minimumClusterSize = minimumClusterSize;
var removeListener;
//聚合
function customStyle() {
if (Cesium.defined(removeListener)) {
removeListener();
removeListener = undefined;
} else {
removeListener = this_.dataSources.clustering.clusterEvent.addEventListener(
function (clusteredEntities, cluster) {
cluster.label.show = false;
cluster.billboard.show = true;
cluster.billboard.id = cluster.label.id;
cluster.billboard.verticalOrigin = Cesium.VerticalOrigin.CENTER;
var xx = -1;
for (var i = 0; i < this_.options.colorArr.length; i++) {
if (clusteredEntities.length > this_.options.colorArr[i].num) {
xx = i;
}
}
if (xx == -1) {
cluster.billboard.image = this_.options.img;
} else {
cluster.billboard.image = this_.drawImage(
clusteredEntities.length,
this_.options.colorArr[xx].size,
this_.options.colorArr[xx].color
);
}
}
);
}
// force a re-cluster with the new styling
var pixelRange = this_.dataSources.clustering.pixelRange;
this_.dataSources.clustering.pixelRange = 0;
this_.dataSources.clustering.pixelRange = pixelRange;
}
customStyle();
}
drawImage(text, size, color) {
if (this.clustericon[text + '_' + size + '_' + color]) {
return this.clustericon[text + '_' + size + '_' + color];
}
var canvas = document.createElement('canvas');
canvas.height = size;
canvas.width = size;
var ctx = canvas.getContext('2d');
//画圈
ctx.beginPath();
ctx.arc(size / 2, size / 2, size / 2, 0, Math.PI * 2, true);
ctx.fillStyle = color;
ctx.closePath();
ctx.fill();
ctx.font = '16px bold 楷体';
ctx.fillStyle = '#ffffff';
var tx = (size - (text + '').length * 9) / 2;
ctx.fillText(text, tx, size / 2 + 6);
var canvasdataurl = canvas.toDataURL();
this.clustericon[text + '_' + size + '_' + color] = canvasdataurl;
return canvasdataurl;
}
remove() {
this.viewer.dataSources.remove(this.dataSources);
this.dataSources = null;
this.clustericon = {};
}
}
function randomPointsWithinBbox(xmin, xmax, ymin, ymax, num, type) {
var points = {
type: 'FeatureCollection',
features: [],
};
for (var i = 0; i < num; i++) {
var point = {
type: 'Feature',
properties: {
value: parseInt(Math.random() * 10000000),
},
geometry: {
type: 'Point',
coordinates: [Math.random() * (xmax - xmin) + xmin, Math.random() * (ymax - ymin) + ymin],
},
};
points.features.push(point);
}
return points;
}
var results = randomPointsWithinBbox(-120, -90, 25, 40, 1000, 'geojson');
var clu = new pointCluster({
viewer: viewer,
dataOrUrl: results,
pixelRange: 20,
colorArr: [
{
num: 1,
size: 30,
color: '#1c86d1cc',
},
{
num: 50,
size: 32,
color: '#67c23acc',
},
{
num: 100,
size: 34,
color: '#f56c6ccc',
},
{
num: 200,
size: 36,
color: '#e6a23ccc',
},
],
img: '/marker6.png',
});
</script>
</body>
</html>
Version 98 effect:is Ok
Version 135 effect:
[](https://sandcastle.cesium.com/#c=jVTbjtowEP2VES8kJRhYdR+6XFSVqlWrrlp1pfah7INJBnDr2JEvLGnFv9d2AoRAV/UDvp0zc5gzMcsLqQy8AKphjprZHFZK5rDopGG36IwXYiFSKbSBLcMnVDAFgU81mnwLZ9EBP5fCUCZQLTqxY4InQxgrK1LDpABFRSbzL5IJo78zs2HizVLuol3ORAK7nO4SKMO6DGth8wRMWWAMfw6xALZUQRFCODmNcwjQO+i+Q2qswrnkHEPebtJEraprfQc/HhsX+/FpvZIKIp+HuRTDsZsmXoxb9Hrxec6jmraYtpxzEQCFkgUqw7yQFtFH5dZxC6o0fhAmuqdmQ6rqRbGzbDSsRtwKum/t1yhzNKq8kqJWF8xoawNIpVQZE9SEOrXTR94r6IM3LoYeVAZeoMoKVdYoPz8+K7jpAdQmk4NfpLB6E4XDuIHbn5YKHVDUvCPkCPBWuTiWh875Ry/2RzfDBPqv3M/NbQIv3eyLnUDX1fKnds0Uj0+d3fga3qP86K7fUkMfpFUpRjHhkmZRnTImZoMiitZtXAzTWaunwodFsiNEE5plV5gNJefjAkpSbrVBxcSaoKBLjpmrgVEWz0r+LK9gO+RfqVijo45u/5/ofGe5eyCqkwf2OwQ44+/jcSfpTLQpOc78xWtWPU9W8YiQgcG84L4bB0ub/kJDUq39358MDpRJxrbAsumV5whSTrV2NyvLuU+/6MwmA4c/o3mznNrPW1Sclh6yGc0+VYeEkMnAbS9ZRkq+pKoR8S8)
The result is as follows:
First, move the camera to the lowest point above the ground and only display the ElementCluster in the bottom right corner. Then slowly raise the camera, and at this point, slowly move to view the entity on the left. You will find many 1s appearing.
Thanks for this report @Duan971231 . I am unable to reproduce the issue so far. This seems to depend on camera movement, right? Could you provide a screen capture video to show more precisely how you are moving the camera to produce the buggy clustering?
I have never looked closer at clustering, and am not sure how well-defined its behavior is. But I think that the effect can be observed quite easily when RIGHT-mouse dragging up (to zoom out). Only when that bunch of '1's is then moved into the center of the view, the clustering kicks in.
@lukemckinstry https://github.com/CesiumGS/cesium/pull/13064 You can take a look at this pull request. It's similar to the screen recording provided by the friend above. When the map camera is raised, you can clearly see that there are issues with the aggregation on the left and top sides.
I have already found the problem, which is due to the new version of kdbush. When using the old method, negative numbers would be converted to 2^23 during comparison. Therefore, entities on the left and top would never enter the EntityCluster. Only in the next calculation, when their position on the screen becomes positive, do they get included. ...
thanks for the follow up @Duan971231 and for identifying the root cause 👍 Feel free to open a PR with the fix if you are willing to.
@lukemckinstry The linked PR at https://github.com/CesiumGS/cesium/pull/13064 was opened by Duan971231, and (I assume) should already fix the issue. (I haven't tested it yet, though...)
@lukemckinstry https://github.com/CesiumGS/cesium/pull/13064 This is my PR