bruce-cesium 2.1.8 → 2.2.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/bruce-cesium.es5.js +365 -161
- package/dist/bruce-cesium.es5.js.map +1 -1
- package/dist/bruce-cesium.umd.js +364 -160
- package/dist/bruce-cesium.umd.js.map +1 -1
- package/dist/lib/bruce-cesium.js +1 -1
- package/dist/lib/rendering/render-managers/common/point-clustering.js +398 -158
- package/dist/lib/rendering/render-managers/common/point-clustering.js.map +1 -1
- package/dist/types/bruce-cesium.d.ts +1 -1
- package/dist/types/rendering/render-managers/common/point-clustering.d.ts +6 -25
- package/package.json +1 -1
package/dist/bruce-cesium.es5.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { BruceEvent, Cartes, Carto, Entity as Entity$1, Geometry, Tileset, MathUtils, LRUCache, ZoomControl, Style, EntityTag, Calculator, EntityLod, EntityType, ClientFile, ObjectUtils, DelayQueue, BatchedDataGetter, EntityRelationType, EntityCoords, EntityFilterGetter, EntitySource, MenuItem, EntityRelation, ENVIRONMENT, ProjectView, ProjectViewBookmark, ProjectViewTile, ProjectViewLegacyTile, ProgramKey, Camera } from 'bruce-models';
|
|
2
2
|
import * as Cesium from 'cesium';
|
|
3
|
-
import { Cartesian2, Cartographic, CallbackProperty, Cartesian3, Color, Rectangle, Math as Math$1,
|
|
3
|
+
import { Cartesian2, Cartographic, CallbackProperty, Cartesian3, Color, Rectangle, Math as Math$1, HeightReference, DistanceDisplayCondition, NearFarScalar, Entity, HorizontalOrigin, VerticalOrigin, ClassificationType, ArcType, PolygonHierarchy, ShadowMode, PolylineGraphics, HeadingPitchRoll, Transforms, ColorBlendMode, SceneMode, Primitive, Cesium3DTileFeature, Cesium3DTileColorBlendMode, HeadingPitchRange, KmlDataSource, OrthographicFrustum, JulianDate, createOsmBuildings, Cesium3DTileStyle, createWorldTerrain, EllipsoidTerrainProvider, CesiumTerrainProvider, BingMapsImageryProvider, BingMapsStyle, MapboxImageryProvider, MapboxStyleImageryProvider, ArcGisMapServerImageryProvider, OpenStreetMapImageryProvider, GridImageryProvider, GeographicTilingScheme, ImageryLayer, UrlTemplateImageryProvider, TileMapServiceImageryProvider, IonImageryProvider, Cesium3DTileset, Matrix4, Matrix3, IonResource, CesiumInspector, ColorMaterialProperty, EasingFunction, GeometryInstance, EllipsoidGeodesic, sampleTerrainMostDetailed, PolygonPipeline } from 'cesium';
|
|
4
4
|
|
|
5
5
|
var TIME_LAG = 300;
|
|
6
6
|
var POSITION_CHECK_TIMER = 950;
|
|
@@ -2711,19 +2711,208 @@ var Quad = /** @class */ (function () {
|
|
|
2711
2711
|
this.southeast.Remove(point);
|
|
2712
2712
|
}
|
|
2713
2713
|
};
|
|
2714
|
+
Quad.prototype.GetDistanceToQuad = function (pos3d) {
|
|
2715
|
+
var minLat = this.boundary.y - this.boundary.h;
|
|
2716
|
+
var maxLat = this.boundary.y + this.boundary.h;
|
|
2717
|
+
var minLon = this.boundary.x - this.boundary.w;
|
|
2718
|
+
var maxLon = this.boundary.x + this.boundary.w;
|
|
2719
|
+
var points = [
|
|
2720
|
+
// Corners.
|
|
2721
|
+
new Cartesian3(minLon, minLat, 0),
|
|
2722
|
+
new Cartesian3(minLon, maxLat, 0),
|
|
2723
|
+
new Cartesian3(maxLon, minLat, 0),
|
|
2724
|
+
new Cartesian3(maxLon, maxLat, 0),
|
|
2725
|
+
// Center.
|
|
2726
|
+
new Cartesian3(this.boundary.x, this.boundary.y, 0)
|
|
2727
|
+
];
|
|
2728
|
+
var shortest = Number.MAX_VALUE;
|
|
2729
|
+
for (var _i = 0, points_1 = points; _i < points_1.length; _i++) {
|
|
2730
|
+
var point = points_1[_i];
|
|
2731
|
+
var distance = Cartesian3.distance(pos3d, point);
|
|
2732
|
+
if (distance < shortest) {
|
|
2733
|
+
shortest = distance;
|
|
2734
|
+
}
|
|
2735
|
+
}
|
|
2736
|
+
return shortest;
|
|
2737
|
+
};
|
|
2714
2738
|
return Quad;
|
|
2715
2739
|
}());
|
|
2740
|
+
var _clusterImageCache = new LRUCache(500);
|
|
2741
|
+
var _clusterImageLoadedCache = new LRUCache(500);
|
|
2742
|
+
function _loadClusterImage(params) {
|
|
2743
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
2744
|
+
var size, txtColor, bgColor, text, iconUrl, key, cacheData, prom;
|
|
2745
|
+
return __generator(this, function (_a) {
|
|
2746
|
+
switch (_a.label) {
|
|
2747
|
+
case 0:
|
|
2748
|
+
size = params.size, txtColor = params.txtColor, bgColor = params.bgColor, text = params.text, iconUrl = params.iconUrl;
|
|
2749
|
+
key = "".concat(size, "-").concat(txtColor, "-").concat(bgColor, "-").concat(text, "-").concat(iconUrl);
|
|
2750
|
+
cacheData = _clusterImageCache.Get(key);
|
|
2751
|
+
if (!cacheData) return [3 /*break*/, 2];
|
|
2752
|
+
return [4 /*yield*/, cacheData];
|
|
2753
|
+
case 1: return [2 /*return*/, _a.sent()];
|
|
2754
|
+
case 2:
|
|
2755
|
+
prom = new Promise(function (res, rej) {
|
|
2756
|
+
var canvas = document.createElement("canvas");
|
|
2757
|
+
canvas.width = size;
|
|
2758
|
+
canvas.height = size;
|
|
2759
|
+
var ctx = canvas.getContext("2d");
|
|
2760
|
+
var WHITESPACE_PADDING_PERCENT = 0.05;
|
|
2761
|
+
var radius = (size / 2) - (size * WHITESPACE_PADDING_PERCENT);
|
|
2762
|
+
var drawWithoutImage = function (img) {
|
|
2763
|
+
ctx.beginPath();
|
|
2764
|
+
ctx.arc(size / 2, size / 2, radius, 0, 2 * Math.PI, false);
|
|
2765
|
+
var fill = null;
|
|
2766
|
+
var txt = null;
|
|
2767
|
+
if (img) {
|
|
2768
|
+
var brightness = calculateImageBrightness(img);
|
|
2769
|
+
fill = brightness < 128 ? "white" : "#114d78";
|
|
2770
|
+
txt = brightness < 128 ? "black" : "white";
|
|
2771
|
+
}
|
|
2772
|
+
else {
|
|
2773
|
+
fill = bgColor ? bgColor : "#114d78";
|
|
2774
|
+
txt = txtColor ? txtColor : "white";
|
|
2775
|
+
}
|
|
2776
|
+
ctx.fillStyle = fill;
|
|
2777
|
+
ctx.fill();
|
|
2778
|
+
var maxTextWidth = size * 0.7;
|
|
2779
|
+
var maxTextHeight = size * 0.7;
|
|
2780
|
+
var minTextSize = Math.floor(size / 12);
|
|
2781
|
+
var textSize = findOptimalFontSize(text, maxTextWidth, maxTextHeight, minTextSize);
|
|
2782
|
+
ctx.font = "bold ".concat(textSize, "px Arial");
|
|
2783
|
+
ctx.fillStyle = txt;
|
|
2784
|
+
ctx.textAlign = "center";
|
|
2785
|
+
ctx.textBaseline = "middle";
|
|
2786
|
+
ctx.fillText(text, size / 2, size / 2);
|
|
2787
|
+
};
|
|
2788
|
+
var drawWithImage = function (img) {
|
|
2789
|
+
var aspectRatio = img.width / img.height;
|
|
2790
|
+
var imageSize = Math.min(radius, img.width, img.height);
|
|
2791
|
+
if (imageSize / aspectRatio > radius) {
|
|
2792
|
+
imageSize = radius * aspectRatio;
|
|
2793
|
+
}
|
|
2794
|
+
var imageX = (size - imageSize) / 2;
|
|
2795
|
+
var imageY = (size - imageSize) / 2 - imageSize / 3;
|
|
2796
|
+
ctx.beginPath();
|
|
2797
|
+
ctx.arc(size / 2, size / 2, radius, 0, 2 * Math.PI, false);
|
|
2798
|
+
var brightness = calculateImageBrightness(img);
|
|
2799
|
+
var bgColor = brightness < 128 ? "white" : "#114d78";
|
|
2800
|
+
var txtColor = brightness < 128 ? "black" : "white";
|
|
2801
|
+
ctx.fillStyle = bgColor;
|
|
2802
|
+
ctx.fill();
|
|
2803
|
+
ctx.shadowColor = "rgba(0, 0, 0, 0.3)";
|
|
2804
|
+
ctx.shadowOffsetX = 3;
|
|
2805
|
+
ctx.shadowOffsetY = 3;
|
|
2806
|
+
ctx.shadowBlur = 5;
|
|
2807
|
+
ctx.drawImage(img, imageX, imageY, imageSize, imageSize);
|
|
2808
|
+
var padding = imageSize / 7;
|
|
2809
|
+
var maxTextWidth = imageSize;
|
|
2810
|
+
var maxTextHeight = imageSize - padding;
|
|
2811
|
+
var minTextSize = Math.floor(imageSize / 5);
|
|
2812
|
+
var textSize = findOptimalFontSize(text, maxTextWidth, maxTextHeight, minTextSize);
|
|
2813
|
+
ctx.font = "bold ".concat(textSize, "px Arial");
|
|
2814
|
+
ctx.fillStyle = txtColor;
|
|
2815
|
+
ctx.textAlign = "center";
|
|
2816
|
+
ctx.textBaseline = "top";
|
|
2817
|
+
ctx.shadowColor = "rgba(0, 0, 0, 0)";
|
|
2818
|
+
ctx.shadowOffsetX = 0;
|
|
2819
|
+
ctx.shadowOffsetY = 0;
|
|
2820
|
+
ctx.shadowBlur = 0;
|
|
2821
|
+
ctx.fillText(text, size / 2, imageY + imageSize + padding);
|
|
2822
|
+
};
|
|
2823
|
+
var findOptimalFontSize = function (text, maxWidth, maxHeight, minSize) {
|
|
2824
|
+
var fontSize = maxHeight;
|
|
2825
|
+
var tempCanvas = document.createElement("canvas");
|
|
2826
|
+
var tempCtx = tempCanvas.getContext("2d");
|
|
2827
|
+
while (fontSize > minSize) {
|
|
2828
|
+
tempCtx.font = "bold ".concat(fontSize, "px Arial");
|
|
2829
|
+
var measuredWidth = tempCtx.measureText(text).width;
|
|
2830
|
+
var measuredHeight = fontSize * 1.2;
|
|
2831
|
+
if (measuredWidth <= maxWidth && measuredHeight <= maxHeight) {
|
|
2832
|
+
break;
|
|
2833
|
+
}
|
|
2834
|
+
fontSize--;
|
|
2835
|
+
}
|
|
2836
|
+
return fontSize;
|
|
2837
|
+
};
|
|
2838
|
+
var calculateImageBrightness = function (img) {
|
|
2839
|
+
var brightness = 0;
|
|
2840
|
+
var tempCanvas = document.createElement("canvas");
|
|
2841
|
+
tempCanvas.width = img.width;
|
|
2842
|
+
tempCanvas.height = img.height;
|
|
2843
|
+
var tempCtx = tempCanvas.getContext("2d");
|
|
2844
|
+
tempCtx.drawImage(img, 0, 0);
|
|
2845
|
+
var imageData = tempCtx.getImageData(0, 0, img.width, img.height).data;
|
|
2846
|
+
for (var i = 0; i < imageData.length; i += 4) {
|
|
2847
|
+
var r = imageData[i];
|
|
2848
|
+
var g = imageData[i + 1];
|
|
2849
|
+
var b = imageData[i + 2];
|
|
2850
|
+
brightness += (r + g + b) / 3;
|
|
2851
|
+
}
|
|
2852
|
+
return Math.round(brightness / (img.width * img.height));
|
|
2853
|
+
};
|
|
2854
|
+
if (iconUrl) {
|
|
2855
|
+
var img_1 = new Image();
|
|
2856
|
+
img_1.crossOrigin = "anonymous";
|
|
2857
|
+
img_1.src = iconUrl;
|
|
2858
|
+
img_1.onload = function () {
|
|
2859
|
+
if (size > 50) {
|
|
2860
|
+
drawWithImage(img_1);
|
|
2861
|
+
}
|
|
2862
|
+
else {
|
|
2863
|
+
drawWithoutImage(img_1);
|
|
2864
|
+
}
|
|
2865
|
+
res(canvas);
|
|
2866
|
+
};
|
|
2867
|
+
img_1.onerror = function () {
|
|
2868
|
+
drawWithoutImage();
|
|
2869
|
+
res(canvas);
|
|
2870
|
+
};
|
|
2871
|
+
}
|
|
2872
|
+
else {
|
|
2873
|
+
drawWithoutImage();
|
|
2874
|
+
res(canvas);
|
|
2875
|
+
}
|
|
2876
|
+
});
|
|
2877
|
+
_clusterImageCache.Set(key, prom);
|
|
2878
|
+
prom.then(function (canvas) {
|
|
2879
|
+
_clusterImageLoadedCache.Set(key, canvas);
|
|
2880
|
+
_clusterImageCache.Set(key, null);
|
|
2881
|
+
});
|
|
2882
|
+
return [4 /*yield*/, prom];
|
|
2883
|
+
case 3: return [2 /*return*/, _a.sent()];
|
|
2884
|
+
}
|
|
2885
|
+
});
|
|
2886
|
+
});
|
|
2887
|
+
}
|
|
2888
|
+
function getClusterImage(params) {
|
|
2889
|
+
var size = params.size, txtColor = params.txtColor, bgColor = params.bgColor, text = params.text, iconUrl = params.iconUrl;
|
|
2890
|
+
var key = "".concat(size, "-").concat(txtColor, "-").concat(bgColor, "-").concat(text, "-").concat(iconUrl);
|
|
2891
|
+
var cacheData = _clusterImageLoadedCache.Get(key);
|
|
2892
|
+
// If available then return.
|
|
2893
|
+
if (cacheData) {
|
|
2894
|
+
return cacheData;
|
|
2895
|
+
}
|
|
2896
|
+
// If not available then queue for it to cook.
|
|
2897
|
+
else {
|
|
2898
|
+
_loadClusterImage(params);
|
|
2899
|
+
}
|
|
2900
|
+
return null;
|
|
2901
|
+
}
|
|
2902
|
+
var FORCE_UPDATE_BATCH_SIZE = 1000;
|
|
2903
|
+
var FORCE_UPDATE_BATCH_DELAY = 100;
|
|
2716
2904
|
var PointClustering = /** @class */ (function () {
|
|
2717
2905
|
function PointClustering(register, menuItemId) {
|
|
2718
2906
|
var _this = this;
|
|
2719
2907
|
this.disposed = false;
|
|
2720
2908
|
this.registeredEntityIds = new Set();
|
|
2909
|
+
// Queue to force update entities.
|
|
2910
|
+
this.updateEntityQueue = [];
|
|
2721
2911
|
this.register = register;
|
|
2722
2912
|
this.viewer = register.Viewer;
|
|
2723
2913
|
this.menuItemId = menuItemId;
|
|
2724
|
-
this.updateClusterSpacing(0);
|
|
2725
2914
|
var boundary = new Rectangle$1(0, 0, 360, 180);
|
|
2726
|
-
this.quadTree = new Quad(boundary,
|
|
2915
|
+
this.quadTree = new Quad(boundary, 30);
|
|
2727
2916
|
this.prevClusteredEntities = new Set();
|
|
2728
2917
|
this.currClusteredEntities = new Set();
|
|
2729
2918
|
this.clusterEntities = new Map();
|
|
@@ -2732,6 +2921,39 @@ var PointClustering = /** @class */ (function () {
|
|
|
2732
2921
|
}, 1000);
|
|
2733
2922
|
this.listenCamera();
|
|
2734
2923
|
}
|
|
2924
|
+
PointClustering.prototype.queueForceUpdate = function (entityIds) {
|
|
2925
|
+
for (var i = 0; i < entityIds.length; i++) {
|
|
2926
|
+
if (this.updateEntityQueue.includes(entityIds[i])) {
|
|
2927
|
+
continue;
|
|
2928
|
+
}
|
|
2929
|
+
this.updateEntityQueue.push(entityIds[i]);
|
|
2930
|
+
}
|
|
2931
|
+
this.runForceUpdateQueue();
|
|
2932
|
+
};
|
|
2933
|
+
PointClustering.prototype.runForceUpdateQueue = function () {
|
|
2934
|
+
var _this = this;
|
|
2935
|
+
if (!this.updateEntityQueue.length) {
|
|
2936
|
+
return;
|
|
2937
|
+
}
|
|
2938
|
+
if (this.queueInterval) {
|
|
2939
|
+
return;
|
|
2940
|
+
}
|
|
2941
|
+
this.queueInterval = setInterval(function () {
|
|
2942
|
+
if (_this.disposed) {
|
|
2943
|
+
clearInterval(_this.queueInterval);
|
|
2944
|
+
_this.queueInterval = null;
|
|
2945
|
+
return;
|
|
2946
|
+
}
|
|
2947
|
+
var ids = _this.updateEntityQueue.splice(0, FORCE_UPDATE_BATCH_SIZE);
|
|
2948
|
+
_this.register.ForceUpdate({
|
|
2949
|
+
entityIds: ids
|
|
2950
|
+
});
|
|
2951
|
+
if (!_this.updateEntityQueue.length) {
|
|
2952
|
+
clearInterval(_this.queueInterval);
|
|
2953
|
+
_this.queueInterval = null;
|
|
2954
|
+
}
|
|
2955
|
+
}, FORCE_UPDATE_BATCH_DELAY);
|
|
2956
|
+
};
|
|
2735
2957
|
/**
|
|
2736
2958
|
* Starts listening to camera changes.
|
|
2737
2959
|
* This will trigger the clustering update whenever camera is moved.
|
|
@@ -2786,6 +3008,7 @@ var PointClustering = /** @class */ (function () {
|
|
|
2786
3008
|
this.clusterEntities.clear();
|
|
2787
3009
|
this.unlistenCamera();
|
|
2788
3010
|
this.disposed = true;
|
|
3011
|
+
this.updateEntityQueue = [];
|
|
2789
3012
|
// Restore entities.
|
|
2790
3013
|
var toUpdateIds = [];
|
|
2791
3014
|
for (var _c = 0, _d = Array.from(this.registeredEntityIds); _c < _d.length; _c++) {
|
|
@@ -2813,8 +3036,8 @@ var PointClustering = /** @class */ (function () {
|
|
|
2813
3036
|
PointClustering.prototype.calculateCentroid = function (points) {
|
|
2814
3037
|
var lonSum = 0;
|
|
2815
3038
|
var latSum = 0;
|
|
2816
|
-
for (var _i = 0,
|
|
2817
|
-
var point =
|
|
3039
|
+
for (var _i = 0, points_2 = points; _i < points_2.length; _i++) {
|
|
3040
|
+
var point = points_2[_i];
|
|
2818
3041
|
lonSum += point.lon;
|
|
2819
3042
|
latSum += point.lat;
|
|
2820
3043
|
}
|
|
@@ -2834,9 +3057,10 @@ var PointClustering = /** @class */ (function () {
|
|
|
2834
3057
|
// 1: Update precision.
|
|
2835
3058
|
// This defines how far apart these clusters can be.
|
|
2836
3059
|
var cameraHeight = this.viewer.camera.positionCartographic.height;
|
|
2837
|
-
this.
|
|
3060
|
+
this.getClusterSpacing(cameraHeight);
|
|
2838
3061
|
// 2: Get clusters.
|
|
2839
3062
|
var _a = this.getClusters(), clusters = _a.clusters, noLongerClustered = _a.noLongerClustered;
|
|
3063
|
+
var entitiesToUpdate = [];
|
|
2840
3064
|
// 3: Remove all cesium cluster entities that are no longer clustered.
|
|
2841
3065
|
for (var _i = 0, _b = Array.from(noLongerClustered); _i < _b.length; _i++) {
|
|
2842
3066
|
var id = _b[_i];
|
|
@@ -2853,193 +3077,180 @@ var PointClustering = /** @class */ (function () {
|
|
|
2853
3077
|
});
|
|
2854
3078
|
if (rego && rego.suppressShow) {
|
|
2855
3079
|
rego.suppressShow = false;
|
|
2856
|
-
|
|
2857
|
-
entityIds: [id],
|
|
2858
|
-
});
|
|
3080
|
+
entitiesToUpdate.push(id);
|
|
2859
3081
|
}
|
|
2860
3082
|
}
|
|
2861
3083
|
}
|
|
2862
3084
|
var getScale = function (count) {
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
scale =
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
return
|
|
3085
|
+
// const MIN_SCALE = 15;
|
|
3086
|
+
// const MAX_SCALE = 80;
|
|
3087
|
+
// const SCALE_PER_POINT = 1.01;
|
|
3088
|
+
// let scale = MIN_SCALE + (count * SCALE_PER_POINT);
|
|
3089
|
+
// scale = Math.min(scale, MAX_SCALE);
|
|
3090
|
+
// return scale;
|
|
3091
|
+
if (count >= 10000) {
|
|
3092
|
+
return 140;
|
|
3093
|
+
}
|
|
3094
|
+
if (count >= 1000) {
|
|
3095
|
+
return 120;
|
|
3096
|
+
}
|
|
3097
|
+
if (count >= 100) {
|
|
3098
|
+
return 90;
|
|
3099
|
+
}
|
|
3100
|
+
if (count >= 10) {
|
|
3101
|
+
return 80;
|
|
3102
|
+
}
|
|
3103
|
+
return 70;
|
|
2882
3104
|
};
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
3105
|
+
/**
|
|
3106
|
+
* Generate circle with label in center.
|
|
3107
|
+
* @param count
|
|
3108
|
+
* @returns
|
|
3109
|
+
*/
|
|
3110
|
+
var getCanvas = function (count) {
|
|
3111
|
+
var params = {
|
|
3112
|
+
size: getScale(count),
|
|
3113
|
+
txtColor: _this.pointColorTxt,
|
|
3114
|
+
bgColor: _this.pointColorBg,
|
|
3115
|
+
text: String(count),
|
|
3116
|
+
iconUrl: _this.iconUrl
|
|
3117
|
+
};
|
|
3118
|
+
return getClusterImage(params);
|
|
3119
|
+
};
|
|
3120
|
+
var _loop_1 = function (cluster) {
|
|
2886
3121
|
var clusterId = cluster.center.id;
|
|
2887
|
-
var clusterEntity =
|
|
2888
|
-
var centroid =
|
|
3122
|
+
var clusterEntity = this_1.clusterEntities.get(clusterId);
|
|
3123
|
+
var centroid = this_1.calculateCentroid(cluster.points);
|
|
2889
3124
|
var count = cluster.points.length;
|
|
2890
3125
|
if (clusterEntity) {
|
|
2891
3126
|
clusterEntity.position = Cartesian3.fromDegrees(centroid.lon, centroid.lat, 150);
|
|
2892
|
-
clusterEntity.
|
|
2893
|
-
|
|
2894
|
-
|
|
3127
|
+
clusterEntity.billboard.image = new CallbackProperty(function () {
|
|
3128
|
+
return getCanvas(count);
|
|
3129
|
+
}, false),
|
|
3130
|
+
clusterEntity.billboard.width = getScale(cluster.points.length);
|
|
2895
3131
|
clusterEntity.billboard.height = getScale(cluster.points.length);
|
|
2896
3132
|
}
|
|
2897
3133
|
else {
|
|
2898
|
-
clusterEntity =
|
|
3134
|
+
clusterEntity = this_1.viewer.entities.add({
|
|
2899
3135
|
position: Cartesian3.fromDegrees(centroid.lon, centroid.lat, 150),
|
|
2900
|
-
point: {
|
|
2901
|
-
heightReference: HeightReference.NONE,
|
|
2902
|
-
pixelSize: getScale(count),
|
|
2903
|
-
color: this.pointColorBg ? this.pointColorBg : Color.fromCssColorString("#4287f5")
|
|
2904
|
-
},
|
|
2905
3136
|
billboard: {
|
|
2906
3137
|
heightReference: HeightReference.NONE,
|
|
2907
|
-
image:
|
|
3138
|
+
image: new CallbackProperty(function () {
|
|
3139
|
+
return getCanvas(count);
|
|
3140
|
+
}, false),
|
|
2908
3141
|
width: getScale(count),
|
|
2909
3142
|
height: getScale(count),
|
|
2910
3143
|
verticalOrigin: VerticalOrigin.CENTER,
|
|
2911
3144
|
horizontalOrigin: HorizontalOrigin.CENTER,
|
|
2912
|
-
disableDepthTestDistance: Number.POSITIVE_INFINITY
|
|
3145
|
+
disableDepthTestDistance: Number.POSITIVE_INFINITY,
|
|
3146
|
+
scaleByDistance: new NearFarScalar(1.5e2, 0.5, 3.0e7, 0.1),
|
|
2913
3147
|
}
|
|
2914
3148
|
});
|
|
2915
|
-
|
|
3149
|
+
this_1.clusterEntities.set(clusterId, clusterEntity);
|
|
2916
3150
|
}
|
|
2917
3151
|
for (var i = 0; i < cluster.points.length; i++) {
|
|
2918
3152
|
var entityId = cluster.points[i].id;
|
|
2919
|
-
var rego =
|
|
3153
|
+
var rego = this_1.register.GetRego({
|
|
2920
3154
|
entityId: entityId,
|
|
2921
|
-
menuItemId:
|
|
3155
|
+
menuItemId: this_1.menuItemId
|
|
2922
3156
|
});
|
|
2923
3157
|
if (rego && !rego.suppressShow) {
|
|
2924
3158
|
rego.suppressShow = true;
|
|
2925
|
-
|
|
2926
|
-
entityIds: [entityId],
|
|
2927
|
-
});
|
|
3159
|
+
entitiesToUpdate.push(entityId);
|
|
2928
3160
|
}
|
|
2929
3161
|
}
|
|
3162
|
+
};
|
|
3163
|
+
var this_1 = this;
|
|
3164
|
+
// 5: iterate over clusters and add/update them as Cesium entities.
|
|
3165
|
+
for (var _e = 0, clusters_1 = clusters; _e < clusters_1.length; _e++) {
|
|
3166
|
+
var cluster = clusters_1[_e];
|
|
3167
|
+
_loop_1(cluster);
|
|
2930
3168
|
}
|
|
2931
|
-
|
|
3169
|
+
this.queueForceUpdate(entitiesToUpdate);
|
|
3170
|
+
var _loop_2 = function (clusterId, clusterEntity) {
|
|
2932
3171
|
if (!clusters.find(function (x) { return x.center.id == clusterId; })) {
|
|
2933
|
-
|
|
2934
|
-
|
|
3172
|
+
this_2.viewer.entities.remove(clusterEntity);
|
|
3173
|
+
this_2.clusterEntities.delete(clusterId);
|
|
2935
3174
|
}
|
|
2936
3175
|
};
|
|
2937
|
-
var
|
|
3176
|
+
var this_2 = this;
|
|
2938
3177
|
// 6: Iterate over existing cluster entities and remove those that are no longer clustered.
|
|
2939
3178
|
for (var _f = 0, _g = Array.from(this.clusterEntities); _f < _g.length; _f++) {
|
|
2940
3179
|
var _h = _g[_f], clusterId = _h[0], clusterEntity = _h[1];
|
|
2941
|
-
|
|
3180
|
+
_loop_2(clusterId, clusterEntity);
|
|
2942
3181
|
}
|
|
2943
3182
|
};
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
*/
|
|
2948
|
-
PointClustering.prototype.updateClusterSpacing = function (cameraHeight) {
|
|
2949
|
-
// Camera height thresholds in meters.
|
|
2950
|
-
var cameraHeightThresholds = [2000, 5000, 8000, 13000, 25000, 40000];
|
|
3183
|
+
PointClustering.prototype.getClusterSpacing = function (distanceFromCluster) {
|
|
3184
|
+
// Distance thresholds in meters from the cluster.
|
|
3185
|
+
var distanceThresholds = [3000, 4000, 5300, 6000, 7000];
|
|
2951
3186
|
// Distance increments in degrees.
|
|
2952
|
-
var distanceIncrements = [0.
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
3187
|
+
var distanceIncrements = [0.001, 0.002, 0.01, 0.03, 0.09];
|
|
3188
|
+
var index = 0;
|
|
3189
|
+
if (distanceFromCluster) {
|
|
3190
|
+
for (var i = 0; i < distanceThresholds.length; i++) {
|
|
3191
|
+
if (distanceFromCluster > distanceThresholds[i]) {
|
|
3192
|
+
index = i;
|
|
3193
|
+
}
|
|
2959
3194
|
}
|
|
2960
|
-
spacing += distanceIncrements[i];
|
|
2961
3195
|
}
|
|
2962
|
-
|
|
3196
|
+
return distanceIncrements[index];
|
|
2963
3197
|
};
|
|
2964
|
-
/**
|
|
2965
|
-
* Gathers clusters.
|
|
2966
|
-
* @returns
|
|
2967
|
-
*/
|
|
2968
3198
|
PointClustering.prototype.getClusters = function () {
|
|
2969
3199
|
var _this = this;
|
|
2970
3200
|
this.currClusteredEntities.clear();
|
|
2971
3201
|
var clusters = [];
|
|
2972
3202
|
var processedPoints = new Set();
|
|
2973
3203
|
var cameraPosition = this.viewer.camera.position;
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
//
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
3204
|
+
var MIN_CAMERA_DISTANCE = 5000;
|
|
3205
|
+
var processQuad = function (quad) {
|
|
3206
|
+
// Distance to quad.
|
|
3207
|
+
// TODO: Needs improvement.
|
|
3208
|
+
var distanceToQuad = quad.GetDistanceToQuad(cameraPosition);
|
|
3209
|
+
// Skip quads that are too close.
|
|
3210
|
+
if (distanceToQuad >= MIN_CAMERA_DISTANCE) {
|
|
3211
|
+
for (var _i = 0, _a = quad.points; _i < _a.length; _i++) {
|
|
3212
|
+
var point = _a[_i];
|
|
3213
|
+
// Skip points already processed in previous clusters.
|
|
3214
|
+
if (processedPoints.has(point.id)) {
|
|
3215
|
+
continue;
|
|
3216
|
+
}
|
|
3217
|
+
// Skip points closer than MIN_CAMERA_DISTANCE meters to the camera.
|
|
3218
|
+
var cartesian3 = Cartesian3.fromDegrees(point.lon, point.lat);
|
|
3219
|
+
var distanceFromCluster = Cartesian3.distance(cartesian3, cameraPosition);
|
|
3220
|
+
if (distanceFromCluster <= MIN_CAMERA_DISTANCE) {
|
|
3221
|
+
continue;
|
|
3222
|
+
}
|
|
3223
|
+
var found = [];
|
|
3224
|
+
var nearbyPoints = quad.Query(new Circle(point.lon, point.lat, _this.getClusterSpacing(distanceFromCluster)), found);
|
|
3225
|
+
if (nearbyPoints.length > 1) {
|
|
3226
|
+
var cluster = { center: point, points: [] };
|
|
3227
|
+
for (var _b = 0, nearbyPoints_1 = nearbyPoints; _b < nearbyPoints_1.length; _b++) {
|
|
3228
|
+
var nearby = nearbyPoints_1[_b];
|
|
3229
|
+
if (!cluster.points.includes(nearby)) {
|
|
3230
|
+
cluster.points.push(nearby);
|
|
3231
|
+
processedPoints.add(nearby.id);
|
|
3232
|
+
_this.currClusteredEntities.add(nearby.id);
|
|
3233
|
+
}
|
|
3234
|
+
}
|
|
3235
|
+
clusters.push(cluster);
|
|
2995
3236
|
}
|
|
2996
3237
|
}
|
|
2997
|
-
clusters.push(cluster);
|
|
2998
3238
|
}
|
|
2999
|
-
|
|
3239
|
+
if (quad.divided) {
|
|
3240
|
+
processQuad(quad.northwest);
|
|
3241
|
+
processQuad(quad.northeast);
|
|
3242
|
+
processQuad(quad.southwest);
|
|
3243
|
+
processQuad(quad.southeast);
|
|
3244
|
+
}
|
|
3245
|
+
};
|
|
3246
|
+
processQuad(this.quadTree);
|
|
3000
3247
|
// Filter out clusters with only one point.
|
|
3001
3248
|
var validClusters = clusters.filter(function (cluster) { return cluster.points.length > 1; });
|
|
3002
|
-
// Merge adjacent clusters.
|
|
3003
|
-
var mergedClusters = this.mergeClusters(validClusters);
|
|
3004
3249
|
// Get the entity IDs that are no longer clustered
|
|
3005
3250
|
var noLongerClustered = new Set(Array.from(this.prevClusteredEntities).filter(function (id) { return !_this.currClusteredEntities.has(id); }));
|
|
3006
3251
|
// Update the previous clustered entities ref.
|
|
3007
3252
|
this.prevClusteredEntities = new Set(this.currClusteredEntities);
|
|
3008
|
-
return { clusters:
|
|
3009
|
-
};
|
|
3010
|
-
/**
|
|
3011
|
-
* Merges clusters that are nearby based on the distanceBetweenClusters value.
|
|
3012
|
-
* @param clusters
|
|
3013
|
-
* @returns
|
|
3014
|
-
*/
|
|
3015
|
-
PointClustering.prototype.mergeClusters = function (clusters) {
|
|
3016
|
-
var _a;
|
|
3017
|
-
var mergedClusters = [].concat(clusters);
|
|
3018
|
-
// Keep looping while merges keep happening.
|
|
3019
|
-
var mergeOccurred = true;
|
|
3020
|
-
while (mergeOccurred) {
|
|
3021
|
-
mergeOccurred = false;
|
|
3022
|
-
for (var i = 0; i < mergedClusters.length - 1; i++) {
|
|
3023
|
-
for (var j = i + 1; j < mergedClusters.length; j++) {
|
|
3024
|
-
var cluster1 = mergedClusters[i];
|
|
3025
|
-
var cluster2 = mergedClusters[j];
|
|
3026
|
-
var centerDistance = this.calculateDistance(cluster1.center.lon, cluster1.center.lat, cluster2.center.lon, cluster2.center.lat);
|
|
3027
|
-
var distanceThreshold = this.distanceBetweenClusters;
|
|
3028
|
-
if (centerDistance <= distanceThreshold) {
|
|
3029
|
-
// Merge clusters.
|
|
3030
|
-
(_a = cluster1.points).push.apply(_a, cluster2.points);
|
|
3031
|
-
mergedClusters.splice(j, 1);
|
|
3032
|
-
this.removeClusterEntity(cluster2.center.id);
|
|
3033
|
-
mergeOccurred = true;
|
|
3034
|
-
break;
|
|
3035
|
-
}
|
|
3036
|
-
}
|
|
3037
|
-
if (mergeOccurred) {
|
|
3038
|
-
break;
|
|
3039
|
-
}
|
|
3040
|
-
}
|
|
3041
|
-
}
|
|
3042
|
-
return mergedClusters;
|
|
3253
|
+
return { clusters: validClusters, noLongerClustered: noLongerClustered };
|
|
3043
3254
|
};
|
|
3044
3255
|
/**
|
|
3045
3256
|
* Removes Cesium cluster entity.
|
|
@@ -3067,24 +3278,7 @@ var PointClustering = /** @class */ (function () {
|
|
|
3067
3278
|
PointClustering.prototype.addPoint = function (id, cartesian3) {
|
|
3068
3279
|
var point = this.convertCartesianToCartographic(cartesian3);
|
|
3069
3280
|
point.id = id;
|
|
3070
|
-
this.quadTree.Insert(point);
|
|
3071
|
-
};
|
|
3072
|
-
/**
|
|
3073
|
-
* Calculates rough distance across earth between two points.
|
|
3074
|
-
* @param lon1
|
|
3075
|
-
* @param lat1
|
|
3076
|
-
* @param lon2
|
|
3077
|
-
* @param lat2
|
|
3078
|
-
* @returns
|
|
3079
|
-
*/
|
|
3080
|
-
PointClustering.prototype.calculateDistance = function (lon1, lat1, lon2, lat2) {
|
|
3081
|
-
var lonDelta = Math.abs(lon1 - lon2);
|
|
3082
|
-
var latDelta = Math.abs(lat1 - lat2);
|
|
3083
|
-
// Approximate radius of the Earth in kilometers
|
|
3084
|
-
var earthRadius = 6371;
|
|
3085
|
-
var distance = 2 * Math.asin(Math.sqrt(Math.sin(latDelta / 2) * Math.sin(latDelta / 2) +
|
|
3086
|
-
Math.cos(lat1) * Math.cos(lat2) * Math.sin(lonDelta / 2) * Math.sin(lonDelta / 2))) * earthRadius;
|
|
3087
|
-
return distance;
|
|
3281
|
+
return this.quadTree.Insert(point);
|
|
3088
3282
|
};
|
|
3089
3283
|
/**
|
|
3090
3284
|
* Adds entity to clustering logic.
|
|
@@ -3108,14 +3302,14 @@ var PointClustering = /** @class */ (function () {
|
|
|
3108
3302
|
return false;
|
|
3109
3303
|
}
|
|
3110
3304
|
if (!this.pointColorBg && entity.point) {
|
|
3111
|
-
|
|
3112
|
-
if (
|
|
3305
|
+
var pointColorBg = GetValue$1(this.viewer, entity.point.color);
|
|
3306
|
+
if (pointColorBg) {
|
|
3113
3307
|
var cColor = null;
|
|
3114
|
-
if (
|
|
3115
|
-
cColor = new Color(
|
|
3308
|
+
if (pointColorBg instanceof Object) {
|
|
3309
|
+
cColor = new Color(pointColorBg.red, pointColorBg.green, pointColorBg.blue, pointColorBg.alpha);
|
|
3116
3310
|
}
|
|
3117
|
-
else if (typeof
|
|
3118
|
-
cColor = Color.fromCssColorString(
|
|
3311
|
+
else if (typeof pointColorBg === "string") {
|
|
3312
|
+
cColor = Color.fromCssColorString(pointColorBg);
|
|
3119
3313
|
}
|
|
3120
3314
|
// Determine if text color should instead be black based on background.
|
|
3121
3315
|
// cColor contains r,g,b,a values where r,g,b are in the range [0,1].
|
|
@@ -3127,11 +3321,21 @@ var PointClustering = /** @class */ (function () {
|
|
|
3127
3321
|
else {
|
|
3128
3322
|
this.pointColorTxt = "white";
|
|
3129
3323
|
}
|
|
3324
|
+
this.pointColorBg = cColor.toCssColorString();
|
|
3130
3325
|
}
|
|
3131
3326
|
}
|
|
3132
3327
|
}
|
|
3328
|
+
if (!this.iconUrl && entity.billboard) {
|
|
3329
|
+
var iconUrl = GetValue$1(this.viewer, entity.billboard.image);
|
|
3330
|
+
if (typeof iconUrl == "string") {
|
|
3331
|
+
this.iconUrl = iconUrl;
|
|
3332
|
+
}
|
|
3333
|
+
}
|
|
3334
|
+
var added = this.addPoint(id, pos3d);
|
|
3335
|
+
if (!added) {
|
|
3336
|
+
return false;
|
|
3337
|
+
}
|
|
3133
3338
|
this.registeredEntityIds.add(id);
|
|
3134
|
-
this.addPoint(id, pos3d);
|
|
3135
3339
|
this.updateQueue.Call();
|
|
3136
3340
|
return true;
|
|
3137
3341
|
};
|
|
@@ -10662,7 +10866,7 @@ var ViewRenderEngine;
|
|
|
10662
10866
|
ViewRenderEngine.Render = Render;
|
|
10663
10867
|
})(ViewRenderEngine || (ViewRenderEngine = {}));
|
|
10664
10868
|
|
|
10665
|
-
var VERSION = "2.
|
|
10869
|
+
var VERSION = "2.2.0";
|
|
10666
10870
|
|
|
10667
10871
|
export { VERSION, CesiumViewMonitor, ViewerUtils, MenuItemManager, EntityRenderEngine, MenuItemCreator, VisualsRegister, RenderManager, EntitiesIdsRenderManager, EntitiesLoadedRenderManager, EntitiesRenderManager, EntityRenderManager, TilesetCadRenderManager, TilesetArbRenderManager, TilesetEntitiesRenderManager, TilesetOsmRenderManager, TilesetPointcloudRenderManager, TilesetGooglePhotosRenderManager, DataSourceStaticKmlManager, RelationsRenderManager, SharedGetters, CesiumParabola, ViewRenderEngine, TileRenderEngine, TilesetRenderEngine, CESIUM_INSPECTOR_KEY, ViewUtils, DrawingUtils, MeasureUtils, EntityUtils };
|
|
10668
10872
|
//# sourceMappingURL=bruce-cesium.es5.js.map
|