Skip to content

Commit 0b0ed14

Browse files
authored
Merge pull request #4240 from AnalyticalGraphicsInc/cluster
Label/Billboard/Point clustering
2 parents b2f64b2 + 3a7a39a commit 0b0ed14

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+2950
-1272
lines changed
+172
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8">
5+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
6+
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
7+
<meta name="description" content="Cluster labels, billboards and points.">
8+
<meta name="cesium-sandcastle-labels" content="Tutorials,Showcases">
9+
<title>Cesium Demo</title>
10+
<script type="text/javascript" src="../Sandcastle-header.js"></script>
11+
<script type="text/javascript" src="../../../ThirdParty/requirejs-2.1.20/require.js"></script>
12+
<script type="text/javascript">
13+
require.config({
14+
baseUrl : '../../../Source',
15+
waitSeconds : 60
16+
});
17+
</script>
18+
</head>
19+
<body class="sandcastle-loading" data-sandcastle-bucket="bucket-requirejs.html">
20+
<style>
21+
@import url(../templates/bucket.css);
22+
#toolbar {
23+
background: rgba(42, 42, 42, 0.8);
24+
padding: 4px;
25+
border-radius: 4px;
26+
}
27+
#toolbar input {
28+
vertical-align: middle;
29+
padding-top: 2px;
30+
padding-bottom: 2px;
31+
}
32+
</style>
33+
<div id="cesiumContainer" class="fullSize"></div>
34+
<div id="loadingOverlay"><h1>Loading...</h1></div>
35+
<div id="toolbar">
36+
<table>
37+
<tbody><tr>
38+
<td>Pixel Range</td>
39+
<td>
40+
<input type="range" min="1" max="200" step="1" data-bind="value: pixelRange, valueUpdate: 'input'">
41+
<input type="text" size="2" data-bind="value: pixelRange">
42+
</td>
43+
</tr>
44+
<tr>
45+
<td>Minimum Cluster Size</td>
46+
<td>
47+
<input type="range" min="2" max="20" step="1" data-bind="value: minimumClusterSize, valueUpdate: 'input'">
48+
<input type="text" size="2" data-bind="value: minimumClusterSize">
49+
</td>
50+
</tr>
51+
<tr><td><input type="checkbox" data-bind="checked: enabled"/>Enabled</td></tr>
52+
<tr><td><input type="checkbox" data-bind="checked: customStyle"/>Custom Styling</td></tr>
53+
</tbody>
54+
</table>
55+
</div>
56+
<script id="cesium_sandcastle_script">
57+
function startup(Cesium) {
58+
'use strict';
59+
//Sandcastle_Begin
60+
var viewer = new Cesium.Viewer('cesiumContainer');
61+
62+
var options = {
63+
camera : viewer.scene.camera,
64+
canvas : viewer.scene.canvas
65+
};
66+
var dataSourcePromise = viewer.dataSources.add(Cesium.KmlDataSource.load('../../SampleData/kml/facilities/facilities.kml', options));
67+
dataSourcePromise.then(function(dataSource) {
68+
var pixelRange = 15;
69+
var minimumClusterSize = 3;
70+
var enabled = true;
71+
72+
dataSource.clustering.enabled = enabled;
73+
dataSource.clustering.pixelRange = pixelRange;
74+
dataSource.clustering.minimumClusterSize = minimumClusterSize;
75+
76+
var removeListener;
77+
78+
var pinBuilder = new Cesium.PinBuilder();
79+
var pin50 = pinBuilder.fromText('50+', Cesium.Color.RED, 48).toDataURL();
80+
var pin40 = pinBuilder.fromText('40+', Cesium.Color.ORANGE, 48).toDataURL();
81+
var pin30 = pinBuilder.fromText('30+', Cesium.Color.YELLOW, 48).toDataURL();
82+
var pin20 = pinBuilder.fromText('20+', Cesium.Color.GREEN, 48).toDataURL();
83+
var pin10 = pinBuilder.fromText('10+', Cesium.Color.BLUE, 48).toDataURL();
84+
85+
var singleDigitPins = new Array(8);
86+
for (var i = 0; i < singleDigitPins.length; ++i) {
87+
singleDigitPins[i] = pinBuilder.fromText('' + (i + 2), Cesium.Color.VIOLET, 48).toDataURL();
88+
}
89+
90+
function customStyle() {
91+
if (Cesium.defined(removeListener)) {
92+
removeListener();
93+
removeListener = undefined;
94+
} else {
95+
removeListener = dataSource.clustering.clusterEvent.addEventListener(function(clusteredEntities, cluster) {
96+
cluster.label.show = false;
97+
cluster.billboard.show = true;
98+
cluster.billboard.verticalOrigin = Cesium.VerticalOrigin.BOTTOM;
99+
100+
if (clusteredEntities.length >= 50) {
101+
cluster.billboard.image = pin50;
102+
} else if (clusteredEntities.length >= 40) {
103+
cluster.billboard.image = pin40;
104+
} else if (clusteredEntities.length >= 30) {
105+
cluster.billboard.image = pin30;
106+
} else if (clusteredEntities.length >= 20) {
107+
cluster.billboard.image = pin20;
108+
} else if (clusteredEntities.length >= 10) {
109+
cluster.billboard.image = pin10;
110+
} else {
111+
cluster.billboard.image = singleDigitPins[clusteredEntities.length - 2];
112+
}
113+
});
114+
}
115+
116+
// force a re-cluster with the new styling
117+
var pixelRange = dataSource.clustering.pixelRange;
118+
dataSource.clustering.pixelRange = 0;
119+
dataSource.clustering.pixelRange = pixelRange;
120+
}
121+
122+
// start with custom style
123+
customStyle();
124+
125+
var viewModel = {
126+
pixelRange: pixelRange,
127+
minimumClusterSize: minimumClusterSize,
128+
enabled : enabled,
129+
customStyle : true
130+
};
131+
Cesium.knockout.track(viewModel);
132+
133+
var toolbar = document.getElementById('toolbar');
134+
Cesium.knockout.applyBindings(viewModel, toolbar);
135+
136+
function subscribeParameter(name) {
137+
Cesium.knockout.getObservable(viewModel, name).subscribe(
138+
function(newValue) {
139+
dataSource.clustering[name] = newValue;
140+
}
141+
);
142+
}
143+
144+
subscribeParameter('pixelRange');
145+
subscribeParameter('minimumClusterSize');
146+
subscribeParameter('enabled');
147+
Cesium.knockout.getObservable(viewModel, 'customStyle').subscribe(customStyle);
148+
149+
var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
150+
handler.setInputAction(function(movement) {
151+
var pickedLabel = viewer.scene.pick(movement.position);
152+
if (Cesium.defined(pickedLabel)) {
153+
var ids = pickedLabel.id;
154+
if (Cesium.isArray(ids)) {
155+
for (var i = 0; i < ids.length; ++i) {
156+
ids[i].label.fillColor = Cesium.Color.RED;
157+
}
158+
}
159+
}
160+
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
161+
});
162+
//Sandcastle_End
163+
Sandcastle.finishedLoading();
164+
}
165+
if (typeof Cesium !== "undefined") {
166+
startup(Cesium);
167+
} else if (typeof require === "function") {
168+
require(["Cesium"], startup);
169+
}
170+
</script>
171+
</body>
172+
</html>
19.4 KB
Loading

Apps/Sandcastle/gallery/development/Labels.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -181,4 +181,4 @@
181181
}
182182
</script>
183183
</body>
184-
</html>
184+
</html>

CHANGES.md

+9-3
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,19 @@ Change Log
33

44
### 1.26 - 2016-10-03
55

6+
* Deprecated
7+
* The `scene` parameter for creating `BillboardVisualizer`, `LabelVisualizer`, and `PointVisualizer` has been deprecated and will be removed in 1.28. Instead, pass an instance of `EntityCluster`.
68
* Breaking changes
79
* Vertex texture fetch is now required to be supported to render polylines. Maximum vertex texture image units must be greater than zero.
10+
* Removed `castShadows` and `receiveShadows` properties from `Model`, `Primitive`, and `Globe`. Instead, use `shadows` with the `ShadowMode` enum, e.g. `model.shadows = ShadowMode.ENABLED`.
11+
* `Viewer.terrainShadows` now uses the `ShadowMode` enum instead of a Boolean, e.g. `viewer.terrainShadows = ShadowMode.RECEIVE_ONLY`.
12+
* Removed the default gamma correction for Bing Maps aerial imagery, because it is no longer an improvement to current versions of the tiles. To restore the previous look, set the `defaultGamma` property of your `BingMapsImageryProvider` instance to 1.3.
813
* Fixed billboard rotation when sized in meters. [#3979](https://github.com/AnalyticalGraphicsInc/cesium/issues/3979)
9-
* Added `DebugCameraPrimitive` to visualize the view frustum of a camera.
10-
* Fixed touch events for the timeline [#4305](https://github.com/AnalyticalGraphicsInc/cesium/pull/4305)
11-
* Removed the default gamma correction for Bing Maps aerial imagery, because we no longer think it is an improvement in current versions of the tiles. To restore the previous look, set the `defaultGamma` property of your `BingMapsImageryProvider` instance to 1.3.
14+
* Fixed timeline touch events. [#4305](https://github.com/AnalyticalGraphicsInc/cesium/pull/4305)
1215
* Fixed a bug that could lead to incorrect terrain heights when using `HeightmapTerrainData` with an encoding in which actual heights were equal to the minimum representable height.
16+
* Fixed a bug in `AttributeCompression.compressTextureCoordinates` and `decompressTextureCoordinates` that could cause a small inaccuracy in the encoded texture coordinates.
17+
* Added `DebugCameraPrimitive` to visualize the view frustum of a camera.
18+
* Added support for clustering `Billboard`, `Label` and `Point` entities. [#4240](https://github.com/AnalyticalGraphicsInc/cesium/pull/4240)
1319

1420
### 1.25 - 2016-09-01
1521

LICENSE.md

+18
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,24 @@ OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
270270
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
271271
THIS SOFTWARE.
272272

273+
### kdbush
274+
275+
https://github.com/mourner/kdbush
276+
277+
> Copyright (c) 2016, Vladimir Agafonkin
278+
>
279+
>Permission to use, copy, modify, and/or distribute this software for any purpose
280+
with or without fee is hereby granted, provided that the above copyright notice
281+
and this permission notice appear in all copies.
282+
>
283+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
284+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
285+
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
286+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
287+
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
288+
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
289+
THIS SOFTWARE.
290+
273291
Tests
274292
=====
275293

Source/Core/AttributeCompression.js

+12-10
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,9 @@ define([
7575
* @param {Cartesian3} vector The normalized vector to be compressed into 2 byte 'oct' encoding.
7676
* @param {Cartesian2} result The 2 byte oct-encoded unit length vector.
7777
* @returns {Cartesian2} The 2 byte oct-encoded unit length vector.
78-
*
78+
*
7979
* @exception {DeveloperError} vector must be normalized.
80-
*
80+
*
8181
* @see AttributeCompression.octEncodeInRange
8282
* @see AttributeCompression.octDecode
8383
*/
@@ -124,14 +124,14 @@ define([
124124

125125
/**
126126
* Decodes a unit-length vector in 2 byte 'oct' encoding to a normalized 3-component vector.
127-
*
127+
*
128128
* @param {Number} x The x component of the oct-encoded unit length vector.
129129
* @param {Number} y The y component of the oct-encoded unit length vector.
130130
* @param {Cartesian3} result The decoded and normalized vector.
131131
* @returns {Cartesian3} The decoded and normalized vector.
132-
*
132+
*
133133
* @exception {DeveloperError} x and y must be an unsigned normalized integer between 0 and 255.
134-
*
134+
*
135135
* @see AttributeCompression.octDecodeInRange
136136
*/
137137
AttributeCompression.octDecode = function(x, y, result) {
@@ -268,7 +268,7 @@ define([
268268
/**
269269
* Pack texture coordinates into a single float. The texture coordinates will only preserve 12 bits of precision.
270270
*
271-
* @param {Cartesian2} textureCoordinates The texture coordinates to compress
271+
* @param {Cartesian2} textureCoordinates The texture coordinates to compress. Both coordinates must be in the range 0.0-1.0.
272272
* @returns {Number} The packed texture coordinates.
273273
*
274274
*/
@@ -279,8 +279,9 @@ define([
279279
}
280280
//>>includeEnd('debug');
281281

282-
var x = textureCoordinates.x === 1.0 ? 4095.0 : (textureCoordinates.x * 4096.0) | 0;
283-
var y = textureCoordinates.y === 1.0 ? 4095.0 : (textureCoordinates.y * 4096.0) | 0;
282+
// Move x and y to the range 0-4095;
283+
var x = (textureCoordinates.x * 4095.0) | 0;
284+
var y = (textureCoordinates.y * 4095.0) | 0;
284285
return 4096.0 * x + y;
285286
};
286287

@@ -303,8 +304,9 @@ define([
303304
//>>includeEnd('debug');
304305

305306
var temp = compressed / 4096.0;
306-
result.x = Math.floor(temp) / 4096.0;
307-
result.y = temp - Math.floor(temp);
307+
var xZeroTo4095 = Math.floor(temp);
308+
result.x = xZeroTo4095 / 4095.0;
309+
result.y = (compressed - xZeroTo4095 * 4096) / 4095;
308310
return result;
309311
};
310312

Source/Core/Geometry.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ define([
158158
/**
159159
* @private
160160
*/
161-
this.boundingSphereCV = undefined;
161+
this.boundingSphereCV = options.boundingSphereCV;
162162
}
163163

164164
/**

Source/Core/GeometryPipeline.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1033,7 +1033,7 @@ define([
10331033
var instance = instances[i];
10341034
if (defined(instance.geometry)) {
10351035
instanceGeometry.push(instance);
1036-
} else {
1036+
} else if (defined(instance.westHemisphereGeometry) && defined(instance.eastHemisphereGeometry)) {
10371037
instanceSplitGeometry.push(instance);
10381038
}
10391039
}

0 commit comments

Comments
 (0)