bruce-cesium 2.1.7 → 2.1.9

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.
@@ -1515,6 +1515,23 @@
1515
1515
  return zoomItem.MinZoom + "-" + zoomItem.MaxZoom + "-" + shouldApplyFlatFix(terrain);
1516
1516
  }
1517
1517
  var _fileValidationCache = {};
1518
+ function getDisplayCondition(min, max) {
1519
+ // Max is required.
1520
+ if (isNaN(+max)) {
1521
+ return undefined;
1522
+ }
1523
+ // Min is optional.
1524
+ if (isNaN(+min)) {
1525
+ min = 0;
1526
+ }
1527
+ // Adjusting slightly because I distrust our initial calculation vs Cesium's one.
1528
+ max = (+max) * 1.2;
1529
+ min = +min;
1530
+ if (min > 0) {
1531
+ min = (+min) * 0.8;
1532
+ }
1533
+ return new Cesium.DistanceDisplayCondition(min, max);
1534
+ }
1518
1535
  (function (EntityRenderEngine) {
1519
1536
  function Render(params) {
1520
1537
  var _a, _b, _c, _d, _e, _f, _g, _h;
@@ -1845,7 +1862,10 @@
1845
1862
  verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
1846
1863
  image: iconUrl,
1847
1864
  heightReference: getHeightRef(style),
1848
- scale: iconScale
1865
+ scale: iconScale,
1866
+ distanceDisplayCondition: getDisplayCondition(params.minDistance, params.maxDistance),
1867
+ // Would be great once we have a setting for this.
1868
+ // translucencyByDistance: getTranslucencyByDistance(params.minDistance, params.maxDistance),
1849
1869
  },
1850
1870
  position: exports.EntityUtils.GetPos({
1851
1871
  viewer: params.viewer,
@@ -1896,7 +1916,8 @@
1896
1916
  extrudedHeight: fillHeight,
1897
1917
  heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
1898
1918
  extrudedHeightReference: exHeightRef,
1899
- zIndex: 1
1919
+ zIndex: 1,
1920
+ distanceDisplayCondition: getDisplayCondition(params.minDistance, params.maxDistance)
1900
1921
  },
1901
1922
  position: pos === null || pos === void 0 ? void 0 : pos.clone(),
1902
1923
  show: false
@@ -1916,7 +1937,8 @@
1916
1937
  extrudedHeight: outlineHeight,
1917
1938
  heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
1918
1939
  extrudedHeightReference: exHeightRef,
1919
- zIndex: 2
1940
+ zIndex: 2,
1941
+ distanceDisplayCondition: getDisplayCondition(params.minDistance, params.maxDistance)
1920
1942
  },
1921
1943
  position: pos === null || pos === void 0 ? void 0 : pos.clone()
1922
1944
  }));
@@ -1938,7 +1960,8 @@
1938
1960
  point: {
1939
1961
  pixelSize: size,
1940
1962
  color: cColor,
1941
- heightReference: getHeightRef(style)
1963
+ heightReference: getHeightRef(style),
1964
+ distanceDisplayCondition: getDisplayCondition(params.minDistance, params.maxDistance)
1942
1965
  },
1943
1966
  position: exports.EntityUtils.GetPos({
1944
1967
  viewer: params.viewer,
@@ -1999,7 +2022,9 @@
1999
2022
  style: pStyle,
2000
2023
  tags: tags,
2001
2024
  viewer: params.viewer,
2002
- api: api
2025
+ api: api,
2026
+ maxDistance: zoomItem.MaxZoom,
2027
+ minDistance: zoomItem.MinZoom
2003
2028
  })];
2004
2029
  case 5:
2005
2030
  cEntity = _d.sent();
@@ -2090,7 +2115,8 @@
2090
2115
  classificationType: Cesium.ClassificationType.TERRAIN,
2091
2116
  arcType: Cesium.ArcType.GEODESIC,
2092
2117
  zIndex: getZIndex(style, entity, params.tags),
2093
- clampToGround: heightRef == Cesium.HeightReference.CLAMP_TO_GROUND
2118
+ clampToGround: heightRef == Cesium.HeightReference.CLAMP_TO_GROUND,
2119
+ distanceDisplayCondition: getDisplayCondition(params.minDistance, params.maxDistance)
2094
2120
  },
2095
2121
  position: exports.EntityUtils.GetPos({
2096
2122
  viewer: params.viewer,
@@ -2138,7 +2164,9 @@
2138
2164
  entity: entity,
2139
2165
  style: lStyle,
2140
2166
  tags: tags,
2141
- viewer: params.viewer
2167
+ viewer: params.viewer,
2168
+ maxDistance: zoomItem.MaxZoom,
2169
+ minDistance: zoomItem.MinZoom
2142
2170
  });
2143
2171
  if (cEntity) {
2144
2172
  cEntity._renderGroup = getRenderGroupId(zoomItem, (_c = params.viewer) === null || _c === void 0 ? void 0 : _c.terrainProvider);
@@ -2210,7 +2238,8 @@
2210
2238
  heightReference: heightRef,
2211
2239
  classificationType: Cesium.ClassificationType.BOTH,
2212
2240
  perPositionHeight: heightRef == Cesium.HeightReference.CLAMP_TO_GROUND ? false : true,
2213
- zIndex: zIndex
2241
+ zIndex: zIndex,
2242
+ distanceDisplayCondition: getDisplayCondition(params.minDistance, params.maxDistance)
2214
2243
  },
2215
2244
  position: exports.EntityUtils.GetPos({
2216
2245
  viewer: params.viewer,
@@ -2235,7 +2264,8 @@
2235
2264
  clampToGround: heightRef == Cesium.HeightReference.CLAMP_TO_GROUND,
2236
2265
  classificationType: Cesium.ClassificationType.TERRAIN,
2237
2266
  arcType: Cesium.ArcType.GEODESIC,
2238
- zIndex: zIndex
2267
+ zIndex: zIndex,
2268
+ distanceDisplayCondition: getDisplayCondition(params.minDistance, params.maxDistance)
2239
2269
  }),
2240
2270
  show: false
2241
2271
  });
@@ -2253,7 +2283,8 @@
2253
2283
  clampToGround: heightRef == Cesium.HeightReference.CLAMP_TO_GROUND,
2254
2284
  classificationType: Cesium.ClassificationType.TERRAIN,
2255
2285
  arcType: Cesium.ArcType.GEODESIC,
2256
- zIndex: zIndex
2286
+ zIndex: zIndex,
2287
+ distanceDisplayCondition: getDisplayCondition(params.minDistance, params.maxDistance)
2257
2288
  }),
2258
2289
  show: false
2259
2290
  });
@@ -2300,7 +2331,9 @@
2300
2331
  entity: entity,
2301
2332
  style: pStyle,
2302
2333
  tags: tags,
2303
- viewer: params.viewer
2334
+ viewer: params.viewer,
2335
+ maxDistance: zoomItem.MaxZoom,
2336
+ minDistance: zoomItem.MinZoom
2304
2337
  });
2305
2338
  if (cEntity) {
2306
2339
  cEntity._renderGroup = getRenderGroupId(zoomItem, (_c = params.viewer) === null || _c === void 0 ? void 0 : _c.terrainProvider);
@@ -2377,7 +2410,8 @@
2377
2410
  shadows: Cesium.ShadowMode.ENABLED,
2378
2411
  colorBlendAmount: blendAmount,
2379
2412
  colorBlendMode: blendMode,
2380
- color: color
2413
+ color: color,
2414
+ distanceDisplayCondition: getDisplayCondition(params.minDistance, params.maxDistance)
2381
2415
  },
2382
2416
  orientation: orientation,
2383
2417
  position: pos,
@@ -2491,7 +2525,9 @@
2491
2525
  api: api,
2492
2526
  fileId: lod.clientFileId
2493
2527
  }),
2494
- lodClientFileId: lod.clientFileId
2528
+ lodClientFileId: lod.clientFileId,
2529
+ maxDistance: zoomItem.MaxZoom,
2530
+ minDistance: zoomItem.MinZoom
2495
2531
  });
2496
2532
  if (cEntity) {
2497
2533
  cEntity._renderGroup = getRenderGroupId(zoomItem, (_e = params.viewer) === null || _e === void 0 ? void 0 : _e.terrainProvider);
@@ -2521,6 +2557,773 @@
2521
2557
  })(Model3d = EntityRenderEngine.Model3d || (EntityRenderEngine.Model3d = {}));
2522
2558
  })(exports.EntityRenderEngine || (exports.EntityRenderEngine = {}));
2523
2559
 
2560
+ function GetValue$1(viewer, obj) {
2561
+ if (obj === null || obj === void 0 ? void 0 : obj.getValue) {
2562
+ return obj.getValue(viewer.scene.lastRenderTime);
2563
+ }
2564
+ return obj;
2565
+ }
2566
+ var Point = /** @class */ (function () {
2567
+ function Point(lon, lat, id) {
2568
+ this.lon = lon;
2569
+ this.lat = lat;
2570
+ this.id = id;
2571
+ }
2572
+ return Point;
2573
+ }());
2574
+ var Circle = /** @class */ (function () {
2575
+ function Circle(x, y, radius) {
2576
+ this.x = x;
2577
+ this.y = y;
2578
+ this.radius = radius;
2579
+ this.width = 2 * radius;
2580
+ this.height = 2 * radius;
2581
+ }
2582
+ Circle.prototype.Intersects = function (range) {
2583
+ var xDist = Math.abs(range.x - this.x);
2584
+ var yDist = Math.abs(range.y - this.y);
2585
+ var r = this.radius;
2586
+ var w = range.width;
2587
+ var h = range.height;
2588
+ if (xDist > (w + r) || yDist > (h + r)) {
2589
+ return false;
2590
+ }
2591
+ if (xDist <= w || yDist <= h) {
2592
+ return true;
2593
+ }
2594
+ var dx = xDist - w;
2595
+ var dy = yDist - h;
2596
+ return (dx * dx + dy * dy <= this.radius * this.radius);
2597
+ };
2598
+ Circle.prototype.Contains = function (point) {
2599
+ var dx = this.x - point.lon;
2600
+ var dy = this.y - point.lat;
2601
+ var distance = Math.sqrt(dx * dx + dy * dy);
2602
+ return distance <= this.radius;
2603
+ };
2604
+ return Circle;
2605
+ }());
2606
+ var Rectangle = /** @class */ (function () {
2607
+ function Rectangle(x, y, w, h) {
2608
+ this.x = x;
2609
+ this.y = y;
2610
+ this.w = w;
2611
+ this.h = h;
2612
+ this.width = 2 * w;
2613
+ this.height = 2 * h;
2614
+ }
2615
+ Rectangle.prototype.Contains = function (point) {
2616
+ return (point.lon >= this.x - this.w &&
2617
+ point.lon < this.x + this.w &&
2618
+ point.lat >= this.y - this.h &&
2619
+ point.lat < this.y + this.h);
2620
+ };
2621
+ Rectangle.prototype.Intersects = function (range) {
2622
+ return !(range.x - range.w > this.x + this.w ||
2623
+ range.x + range.w < this.x - this.w ||
2624
+ range.y - range.h > this.y + this.h ||
2625
+ range.y + range.h < this.y - this.h);
2626
+ };
2627
+ return Rectangle;
2628
+ }());
2629
+ var Quad = /** @class */ (function () {
2630
+ function Quad(boundary, capacity) {
2631
+ this.boundary = boundary;
2632
+ this.capacity = capacity;
2633
+ this.points = [];
2634
+ this.divided = false;
2635
+ }
2636
+ Quad.prototype.Subdivide = function () {
2637
+ var x = this.boundary.x;
2638
+ var y = this.boundary.y;
2639
+ var w = this.boundary.w / 2;
2640
+ var h = this.boundary.h / 2;
2641
+ var ne = new Rectangle(x + w / 2, y - h / 2, w, h);
2642
+ this.northeast = new Quad(ne, this.capacity);
2643
+ var nw = new Rectangle(x - w / 2, y - h / 2, w, h);
2644
+ this.northwest = new Quad(nw, this.capacity);
2645
+ var se = new Rectangle(x + w / 2, y + h / 2, w, h);
2646
+ this.southeast = new Quad(se, this.capacity);
2647
+ var sw = new Rectangle(x - w / 2, y + h / 2, w, h);
2648
+ this.southwest = new Quad(sw, this.capacity);
2649
+ this.divided = true;
2650
+ };
2651
+ Quad.prototype.Insert = function (point) {
2652
+ if (!this.boundary.Contains(point)) {
2653
+ return false;
2654
+ }
2655
+ if (this.points.length < this.capacity) {
2656
+ this.points.push(point);
2657
+ return true;
2658
+ }
2659
+ if (!this.divided) {
2660
+ this.Subdivide();
2661
+ }
2662
+ return (this.northeast.Insert(point) || this.northwest.Insert(point) ||
2663
+ this.southeast.Insert(point) || this.southwest.Insert(point));
2664
+ };
2665
+ Quad.prototype.Query = function (range, found) {
2666
+ if (!found) {
2667
+ found = [];
2668
+ }
2669
+ if (!range.Intersects(this.boundary)) {
2670
+ return found;
2671
+ }
2672
+ for (var _i = 0, _a = this.points; _i < _a.length; _i++) {
2673
+ var p = _a[_i];
2674
+ if (range.Contains(p)) {
2675
+ found.push(p);
2676
+ }
2677
+ }
2678
+ if (this.divided) {
2679
+ this.northwest.Query(range, found);
2680
+ this.northeast.Query(range, found);
2681
+ this.southwest.Query(range, found);
2682
+ this.southeast.Query(range, found);
2683
+ }
2684
+ return found;
2685
+ };
2686
+ Quad.prototype.Find = function (id) {
2687
+ for (var _i = 0, _a = this.points; _i < _a.length; _i++) {
2688
+ var point = _a[_i];
2689
+ if (point.id === id) {
2690
+ return point;
2691
+ }
2692
+ }
2693
+ if (this.divided) {
2694
+ return this.northwest.Find(id) || this.northeast.Find(id) ||
2695
+ this.southwest.Find(id) || this.southeast.Find(id);
2696
+ }
2697
+ return null;
2698
+ };
2699
+ Quad.prototype.Remove = function (point) {
2700
+ var index = this.points.indexOf(point);
2701
+ if (index !== -1) {
2702
+ this.points.splice(index, 1);
2703
+ }
2704
+ if (this.divided) {
2705
+ this.northwest.Remove(point);
2706
+ this.northeast.Remove(point);
2707
+ this.southwest.Remove(point);
2708
+ this.southeast.Remove(point);
2709
+ }
2710
+ };
2711
+ return Quad;
2712
+ }());
2713
+ var _clusterImageCache = new bruceModels.LRUCache(500);
2714
+ var _clusterImageLoadedCache = new bruceModels.LRUCache(500);
2715
+ function _loadClusterImage(params) {
2716
+ return __awaiter(this, void 0, void 0, function () {
2717
+ var size, txtColor, bgColor, text, iconUrl, key, cacheData, prom;
2718
+ return __generator(this, function (_a) {
2719
+ switch (_a.label) {
2720
+ case 0:
2721
+ size = params.size, txtColor = params.txtColor, bgColor = params.bgColor, text = params.text, iconUrl = params.iconUrl;
2722
+ key = "".concat(size, "-").concat(txtColor, "-").concat(bgColor, "-").concat(text, "-").concat(iconUrl);
2723
+ cacheData = _clusterImageCache.Get(key);
2724
+ if (!cacheData) return [3 /*break*/, 2];
2725
+ return [4 /*yield*/, cacheData];
2726
+ case 1: return [2 /*return*/, _a.sent()];
2727
+ case 2:
2728
+ prom = new Promise(function (res, rej) {
2729
+ var canvas = document.createElement("canvas");
2730
+ canvas.width = size;
2731
+ canvas.height = size;
2732
+ var ctx = canvas.getContext("2d");
2733
+ var drawWithoutImage = function (img) {
2734
+ ctx.beginPath();
2735
+ ctx.arc(size / 2, size / 2, size / 2, 0, 2 * Math.PI, false);
2736
+ var fill = null;
2737
+ var txt = null;
2738
+ if (img) {
2739
+ var brightness = calculateImageBrightness(img);
2740
+ // brightness < 128 = light background.
2741
+ fill = brightness < 128 ? "white" : "#114d78";
2742
+ txt = brightness < 128 ? "black" : "white";
2743
+ }
2744
+ else {
2745
+ fill = bgColor ? bgColor : "#114d78";
2746
+ txt = txtColor ? txtColor : "white";
2747
+ }
2748
+ ctx.fillStyle = fill;
2749
+ ctx.fill();
2750
+ var maxTextWidth = size * 0.8;
2751
+ var maxTextHeight = size * 0.8;
2752
+ var minTextSize = Math.floor(size / 10);
2753
+ var textSize = findOptimalFontSize(text, maxTextWidth, maxTextHeight, minTextSize);
2754
+ ctx.font = "bold ".concat(textSize, "px Arial");
2755
+ ctx.fillStyle = txt;
2756
+ ctx.textAlign = "center";
2757
+ ctx.textBaseline = "middle";
2758
+ ctx.fillText(text, size / 2, size / 2);
2759
+ };
2760
+ var drawWithImage = function (img) {
2761
+ var aspectRatio = img.width / img.height;
2762
+ var imageSize = Math.min(size / 2, img.width, img.height);
2763
+ if (imageSize / aspectRatio > size / 2) {
2764
+ imageSize = (size / 2) * aspectRatio;
2765
+ }
2766
+ var imageX = (size - imageSize) / 2;
2767
+ var imageY = (size - imageSize) / 2 - imageSize / 3;
2768
+ ctx.beginPath();
2769
+ ctx.arc(size / 2, size / 2, size / 2, 0, 2 * Math.PI, false);
2770
+ var brightness = calculateImageBrightness(img);
2771
+ var bgColor = brightness < 128 ? "white" : "#114d78";
2772
+ var txtColor = brightness < 128 ? "black" : "white";
2773
+ ctx.fillStyle = bgColor;
2774
+ ctx.fill();
2775
+ ctx.shadowColor = "rgba(0, 0, 0, 0.3)";
2776
+ ctx.shadowOffsetX = 3;
2777
+ ctx.shadowOffsetY = 3;
2778
+ ctx.shadowBlur = 5;
2779
+ ctx.drawImage(img, imageX, imageY, imageSize, imageSize);
2780
+ var padding = imageSize / 6;
2781
+ var maxTextWidth = imageSize;
2782
+ var maxTextHeight = imageSize - padding;
2783
+ var minTextSize = Math.floor(imageSize / 5);
2784
+ var textSize = findOptimalFontSize(text, maxTextWidth, maxTextHeight, minTextSize);
2785
+ ctx.font = "bold ".concat(textSize, "px Arial");
2786
+ ctx.fillStyle = txtColor;
2787
+ ctx.textAlign = "center";
2788
+ ctx.textBaseline = "top";
2789
+ ctx.shadowColor = "rgba(0, 0, 0, 0)";
2790
+ ctx.shadowOffsetX = 0;
2791
+ ctx.shadowOffsetY = 0;
2792
+ ctx.shadowBlur = 0;
2793
+ ctx.fillText(text, size / 2, imageY + imageSize + padding);
2794
+ };
2795
+ var findOptimalFontSize = function (text, maxWidth, maxHeight, minSize) {
2796
+ var fontSize = maxHeight;
2797
+ var tempCanvas = document.createElement("canvas");
2798
+ var tempCtx = tempCanvas.getContext("2d");
2799
+ while (fontSize > minSize) {
2800
+ tempCtx.font = "bold ".concat(fontSize, "px Arial");
2801
+ var measuredWidth = tempCtx.measureText(text).width;
2802
+ var measuredHeight = fontSize * 1.2; // Allowing some padding
2803
+ if (measuredWidth <= maxWidth && measuredHeight <= maxHeight) {
2804
+ break;
2805
+ }
2806
+ fontSize--;
2807
+ }
2808
+ return fontSize;
2809
+ };
2810
+ var calculateImageBrightness = function (img) {
2811
+ var brightness = 0;
2812
+ var tempCanvas = document.createElement("canvas");
2813
+ tempCanvas.width = img.width;
2814
+ tempCanvas.height = img.height;
2815
+ var tempCtx = tempCanvas.getContext("2d");
2816
+ tempCtx.drawImage(img, 0, 0);
2817
+ var imageData = tempCtx.getImageData(0, 0, img.width, img.height).data;
2818
+ for (var i = 0; i < imageData.length; i += 4) {
2819
+ var r = imageData[i];
2820
+ var g = imageData[i + 1];
2821
+ var b = imageData[i + 2];
2822
+ brightness += (r + g + b) / 3;
2823
+ }
2824
+ return Math.round(brightness / (img.width * img.height));
2825
+ };
2826
+ if (iconUrl) {
2827
+ var img_1 = new Image();
2828
+ img_1.crossOrigin = "anonymous";
2829
+ img_1.src = iconUrl;
2830
+ img_1.onload = function () {
2831
+ if (size > 50) {
2832
+ drawWithImage(img_1);
2833
+ }
2834
+ else {
2835
+ drawWithoutImage(img_1);
2836
+ }
2837
+ res(canvas);
2838
+ };
2839
+ img_1.onerror = function () {
2840
+ drawWithoutImage();
2841
+ res(canvas);
2842
+ };
2843
+ }
2844
+ else {
2845
+ drawWithoutImage();
2846
+ res(canvas);
2847
+ }
2848
+ });
2849
+ _clusterImageCache.Set(key, prom);
2850
+ prom.then(function (canvas) {
2851
+ _clusterImageLoadedCache.Set(key, canvas);
2852
+ _clusterImageCache.Set(key, null);
2853
+ });
2854
+ return [4 /*yield*/, prom];
2855
+ case 3: return [2 /*return*/, _a.sent()];
2856
+ }
2857
+ });
2858
+ });
2859
+ }
2860
+ function getClusterImage(params) {
2861
+ var size = params.size, txtColor = params.txtColor, bgColor = params.bgColor, text = params.text, iconUrl = params.iconUrl;
2862
+ var key = "".concat(size, "-").concat(txtColor, "-").concat(bgColor, "-").concat(text, "-").concat(iconUrl);
2863
+ var cacheData = _clusterImageLoadedCache.Get(key);
2864
+ // If available then return.
2865
+ if (cacheData) {
2866
+ return cacheData;
2867
+ }
2868
+ // If not available then queue for it to cook.
2869
+ else {
2870
+ _loadClusterImage(params);
2871
+ }
2872
+ return null;
2873
+ }
2874
+ var PointClustering = /** @class */ (function () {
2875
+ function PointClustering(register, menuItemId) {
2876
+ var _this = this;
2877
+ this.disposed = false;
2878
+ this.registeredEntityIds = new Set();
2879
+ this.register = register;
2880
+ this.viewer = register.Viewer;
2881
+ this.menuItemId = menuItemId;
2882
+ this.updateClusterSpacing(0);
2883
+ var boundary = new Rectangle(0, 0, 360, 180);
2884
+ this.quadTree = new Quad(boundary, 4);
2885
+ this.prevClusteredEntities = new Set();
2886
+ this.currClusteredEntities = new Set();
2887
+ this.clusterEntities = new Map();
2888
+ this.updateQueue = new bruceModels.DelayQueue(function () {
2889
+ _this.doUpdate();
2890
+ }, 1000);
2891
+ this.listenCamera();
2892
+ }
2893
+ /**
2894
+ * Starts listening to camera changes.
2895
+ * This will trigger the clustering update whenever camera is moved.
2896
+ */
2897
+ PointClustering.prototype.listenCamera = function () {
2898
+ var _this = this;
2899
+ var viewer = this.viewer;
2900
+ var lastPos3d;
2901
+ var hasMoved = function () {
2902
+ var _a;
2903
+ var cameraPos = (_a = viewer === null || viewer === void 0 ? void 0 : viewer.camera) === null || _a === void 0 ? void 0 : _a.positionCartographic;
2904
+ if (!cameraPos) {
2905
+ return false;
2906
+ }
2907
+ var pos3d = Cesium.Cartographic.toCartesian(cameraPos);
2908
+ if (!lastPos3d) {
2909
+ lastPos3d = pos3d;
2910
+ return false;
2911
+ }
2912
+ var distance = Cesium.Cartesian3.distance(pos3d, lastPos3d);
2913
+ lastPos3d = pos3d;
2914
+ // 50 meter movement at least.
2915
+ return distance > 50;
2916
+ };
2917
+ this.listenCameraRemoval = viewer.scene.camera.changed.addEventListener(function () {
2918
+ if (hasMoved()) {
2919
+ _this.updateQueue.Call();
2920
+ }
2921
+ });
2922
+ };
2923
+ /**
2924
+ * Stops listening to camera changes.
2925
+ */
2926
+ PointClustering.prototype.unlistenCamera = function () {
2927
+ if (this.listenCameraRemoval) {
2928
+ this.listenCameraRemoval();
2929
+ this.listenCameraRemoval = null;
2930
+ }
2931
+ };
2932
+ /**
2933
+ * Removes all clusters and updates entities to no longer be suppressed.
2934
+ * @returns
2935
+ */
2936
+ PointClustering.prototype.Dispose = function () {
2937
+ if (this.disposed) {
2938
+ return;
2939
+ }
2940
+ for (var _i = 0, _a = Array.from(this.clusterEntities); _i < _a.length; _i++) {
2941
+ var _b = _a[_i], entity = _b[1];
2942
+ this.viewer.entities.remove(entity);
2943
+ }
2944
+ this.clusterEntities.clear();
2945
+ this.unlistenCamera();
2946
+ this.disposed = true;
2947
+ // Restore entities.
2948
+ var toUpdateIds = [];
2949
+ for (var _c = 0, _d = Array.from(this.registeredEntityIds); _c < _d.length; _c++) {
2950
+ var id = _d[_c];
2951
+ var rego = this.register.GetRego({
2952
+ entityId: id,
2953
+ menuItemId: this.menuItemId
2954
+ });
2955
+ if (rego && rego.suppressShow) {
2956
+ rego.suppressShow = false;
2957
+ toUpdateIds.push(id);
2958
+ }
2959
+ }
2960
+ if (toUpdateIds.length) {
2961
+ this.register.ForceUpdate({
2962
+ entityIds: toUpdateIds,
2963
+ });
2964
+ }
2965
+ };
2966
+ /**
2967
+ * Calculates center of given points.
2968
+ * @param points
2969
+ * @returns
2970
+ */
2971
+ PointClustering.prototype.calculateCentroid = function (points) {
2972
+ var lonSum = 0;
2973
+ var latSum = 0;
2974
+ for (var _i = 0, points_1 = points; _i < points_1.length; _i++) {
2975
+ var point = points_1[_i];
2976
+ lonSum += point.lon;
2977
+ latSum += point.lat;
2978
+ }
2979
+ var lonAvg = lonSum / points.length;
2980
+ var latAvg = latSum / points.length;
2981
+ return new Point(lonAvg, latAvg, "");
2982
+ };
2983
+ /**
2984
+ * Gathers current clusters and renders them.
2985
+ * @returns
2986
+ */
2987
+ PointClustering.prototype.doUpdate = function () {
2988
+ var _this = this;
2989
+ if (this.disposed) {
2990
+ return;
2991
+ }
2992
+ // 1: Update precision.
2993
+ // This defines how far apart these clusters can be.
2994
+ var cameraHeight = this.viewer.camera.positionCartographic.height;
2995
+ this.updateClusterSpacing(cameraHeight);
2996
+ // 2: Get clusters.
2997
+ var _a = this.getClusters(), clusters = _a.clusters, noLongerClustered = _a.noLongerClustered;
2998
+ // 3: Remove all cesium cluster entities that are no longer clustered.
2999
+ for (var _i = 0, _b = Array.from(noLongerClustered); _i < _b.length; _i++) {
3000
+ var id = _b[_i];
3001
+ this.removeClusterEntity(id);
3002
+ }
3003
+ // 4: Stop hiding entities that are no longer clustered.
3004
+ var previousEntityIds = new Set(this.registeredEntityIds);
3005
+ for (var _c = 0, _d = Array.from(previousEntityIds); _c < _d.length; _c++) {
3006
+ var id = _d[_c];
3007
+ if (!this.currClusteredEntities.has(id)) {
3008
+ var rego = this.register.GetRego({
3009
+ entityId: id,
3010
+ menuItemId: this.menuItemId
3011
+ });
3012
+ if (rego && rego.suppressShow) {
3013
+ rego.suppressShow = false;
3014
+ this.register.ForceUpdate({
3015
+ entityIds: [id],
3016
+ });
3017
+ }
3018
+ }
3019
+ }
3020
+ var getScale = function (count) {
3021
+ var baseSize = 20;
3022
+ var scalingFactor = 2;
3023
+ var scale = baseSize + scalingFactor * (count - 1);
3024
+ scale = Math.min(scale, 120);
3025
+ return scale;
3026
+ };
3027
+ /**
3028
+ * Generate circle with label in center.
3029
+ * @param count
3030
+ * @returns
3031
+ */
3032
+ var getCanvas = function (count) {
3033
+ var params = {
3034
+ size: getScale(count),
3035
+ txtColor: _this.pointColorTxt,
3036
+ bgColor: _this.pointColorBg,
3037
+ text: String(count),
3038
+ iconUrl: _this.iconUrl
3039
+ };
3040
+ return getClusterImage(params);
3041
+ };
3042
+ var _loop_1 = function (cluster) {
3043
+ var clusterId = cluster.center.id;
3044
+ var clusterEntity = this_1.clusterEntities.get(clusterId);
3045
+ var centroid = this_1.calculateCentroid(cluster.points);
3046
+ var count = cluster.points.length;
3047
+ if (clusterEntity) {
3048
+ clusterEntity.position = Cesium.Cartesian3.fromDegrees(centroid.lon, centroid.lat, 150);
3049
+ clusterEntity.billboard.image = new Cesium.CallbackProperty(function () {
3050
+ return getCanvas(count);
3051
+ }, false),
3052
+ clusterEntity.billboard.width = getScale(cluster.points.length);
3053
+ clusterEntity.billboard.height = getScale(cluster.points.length);
3054
+ }
3055
+ else {
3056
+ clusterEntity = this_1.viewer.entities.add({
3057
+ position: Cesium.Cartesian3.fromDegrees(centroid.lon, centroid.lat, 150),
3058
+ billboard: {
3059
+ heightReference: Cesium.HeightReference.NONE,
3060
+ image: new Cesium.CallbackProperty(function () {
3061
+ return getCanvas(count);
3062
+ }, false),
3063
+ width: getScale(count),
3064
+ height: getScale(count),
3065
+ verticalOrigin: Cesium.VerticalOrigin.CENTER,
3066
+ horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
3067
+ disableDepthTestDistance: Number.POSITIVE_INFINITY
3068
+ }
3069
+ });
3070
+ this_1.clusterEntities.set(clusterId, clusterEntity);
3071
+ }
3072
+ for (var i = 0; i < cluster.points.length; i++) {
3073
+ var entityId = cluster.points[i].id;
3074
+ var rego = this_1.register.GetRego({
3075
+ entityId: entityId,
3076
+ menuItemId: this_1.menuItemId
3077
+ });
3078
+ if (rego && !rego.suppressShow) {
3079
+ rego.suppressShow = true;
3080
+ this_1.register.ForceUpdate({
3081
+ entityIds: [entityId],
3082
+ });
3083
+ }
3084
+ }
3085
+ };
3086
+ var this_1 = this;
3087
+ // 5: iterate over clusters and add/update them as Cesium entities.
3088
+ for (var _e = 0, clusters_1 = clusters; _e < clusters_1.length; _e++) {
3089
+ var cluster = clusters_1[_e];
3090
+ _loop_1(cluster);
3091
+ }
3092
+ var _loop_2 = function (clusterId, clusterEntity) {
3093
+ if (!clusters.find(function (x) { return x.center.id == clusterId; })) {
3094
+ this_2.viewer.entities.remove(clusterEntity);
3095
+ this_2.clusterEntities.delete(clusterId);
3096
+ }
3097
+ };
3098
+ var this_2 = this;
3099
+ // 6: Iterate over existing cluster entities and remove those that are no longer clustered.
3100
+ for (var _f = 0, _g = Array.from(this.clusterEntities); _f < _g.length; _f++) {
3101
+ var _h = _g[_f], clusterId = _h[0], clusterEntity = _h[1];
3102
+ _loop_2(clusterId, clusterEntity);
3103
+ }
3104
+ };
3105
+ /**
3106
+ * Updates how apart clusters can be based on camera distance.
3107
+ * @param cameraHeight
3108
+ */
3109
+ PointClustering.prototype.updateClusterSpacing = function (cameraHeight) {
3110
+ // Camera height thresholds in meters.
3111
+ var cameraHeightThresholds = [4000, 5000, 8000, 13000, 25000, 40000];
3112
+ // Distance increments in degrees.
3113
+ var distanceIncrements = [0.005, 0.01, 0.02, 0.04, 0.1, 0.5];
3114
+ // Find the appropriate spacing based on the camera height.
3115
+ var spacing = 0;
3116
+ for (var i = 0; i < cameraHeightThresholds.length; i++) {
3117
+ if (cameraHeight && cameraHeight < cameraHeightThresholds[i]) {
3118
+ spacing += distanceIncrements[i];
3119
+ break;
3120
+ }
3121
+ spacing += distanceIncrements[i];
3122
+ }
3123
+ this.distanceBetweenClusters = spacing;
3124
+ };
3125
+ /**
3126
+ * Gathers clusters.
3127
+ * @returns
3128
+ */
3129
+ PointClustering.prototype.getClusters = function () {
3130
+ var _this = this;
3131
+ this.currClusteredEntities.clear();
3132
+ var clusters = [];
3133
+ var processedPoints = new Set();
3134
+ var cameraPosition = this.viewer.camera.position;
3135
+ for (var _i = 0, _a = this.quadTree.points; _i < _a.length; _i++) {
3136
+ var point = _a[_i];
3137
+ // Skip points already processed in previous clusters.
3138
+ if (processedPoints.has(point.id)) {
3139
+ continue;
3140
+ }
3141
+ // Skip points closer than 4000 meters to the camera.
3142
+ var cartesian3 = Cesium.Cartesian3.fromDegrees(point.lon, point.lat);
3143
+ if (Cesium.Cartesian3.distance(cartesian3, cameraPosition) <= 4000) {
3144
+ continue;
3145
+ }
3146
+ var found = [];
3147
+ var nearbyPoints = this.quadTree.Query(new Circle(point.lon, point.lat, this.distanceBetweenClusters), found);
3148
+ if (nearbyPoints.length > 1) {
3149
+ var cluster = { center: point, points: [] };
3150
+ for (var _b = 0, nearbyPoints_1 = nearbyPoints; _b < nearbyPoints_1.length; _b++) {
3151
+ var nearby = nearbyPoints_1[_b];
3152
+ if (!cluster.points.includes(nearby)) {
3153
+ cluster.points.push(nearby);
3154
+ processedPoints.add(nearby.id);
3155
+ this.currClusteredEntities.add(nearby.id);
3156
+ }
3157
+ }
3158
+ clusters.push(cluster);
3159
+ }
3160
+ }
3161
+ // Filter out clusters with only one point.
3162
+ var validClusters = clusters.filter(function (cluster) { return cluster.points.length > 1; });
3163
+ // Merge adjacent clusters.
3164
+ var mergedClusters = this.mergeClusters(validClusters);
3165
+ // Get the entity IDs that are no longer clustered
3166
+ var noLongerClustered = new Set(Array.from(this.prevClusteredEntities).filter(function (id) { return !_this.currClusteredEntities.has(id); }));
3167
+ // Update the previous clustered entities ref.
3168
+ this.prevClusteredEntities = new Set(this.currClusteredEntities);
3169
+ return { clusters: mergedClusters, noLongerClustered: noLongerClustered };
3170
+ };
3171
+ /**
3172
+ * Merges clusters that are nearby based on the distanceBetweenClusters value.
3173
+ * @param clusters
3174
+ * @returns
3175
+ */
3176
+ PointClustering.prototype.mergeClusters = function (clusters) {
3177
+ var _a;
3178
+ var mergedClusters = [].concat(clusters);
3179
+ // Keep looping while merges keep happening.
3180
+ var mergeOccurred = true;
3181
+ while (mergeOccurred) {
3182
+ mergeOccurred = false;
3183
+ for (var i = 0; i < mergedClusters.length - 1; i++) {
3184
+ for (var j = i + 1; j < mergedClusters.length; j++) {
3185
+ var cluster1 = mergedClusters[i];
3186
+ var cluster2 = mergedClusters[j];
3187
+ var centerDistance = this.calculateDistance(cluster1.center.lon, cluster1.center.lat, cluster2.center.lon, cluster2.center.lat);
3188
+ var distanceThreshold = this.distanceBetweenClusters;
3189
+ if (centerDistance <= distanceThreshold) {
3190
+ // Merge clusters.
3191
+ (_a = cluster1.points).push.apply(_a, cluster2.points);
3192
+ mergedClusters.splice(j, 1);
3193
+ this.removeClusterEntity(cluster2.center.id);
3194
+ mergeOccurred = true;
3195
+ break;
3196
+ }
3197
+ }
3198
+ if (mergeOccurred) {
3199
+ break;
3200
+ }
3201
+ }
3202
+ }
3203
+ return mergedClusters;
3204
+ };
3205
+ /**
3206
+ * Removes Cesium cluster entity.
3207
+ * @param clusterId
3208
+ */
3209
+ PointClustering.prototype.removeClusterEntity = function (clusterId) {
3210
+ var clusterEntity = this.clusterEntities.get(clusterId);
3211
+ if (clusterEntity) {
3212
+ this.viewer.entities.remove(clusterEntity);
3213
+ this.clusterEntities.delete(clusterId);
3214
+ }
3215
+ };
3216
+ PointClustering.prototype.convertCartesianToCartographic = function (cartesian3) {
3217
+ var carto = Cesium.Cartographic.fromCartesian(cartesian3);
3218
+ var lon = Cesium.Math.toDegrees(carto.longitude);
3219
+ var lat = Cesium.Math.toDegrees(carto.latitude);
3220
+ var id = lon + ',' + lat;
3221
+ return new Point(lon, lat, id);
3222
+ };
3223
+ /**
3224
+ * Adds new entity to the clustering logic.
3225
+ * @param id Bruce entity ID.
3226
+ * @param cartesian3 entity's position.
3227
+ */
3228
+ PointClustering.prototype.addPoint = function (id, cartesian3) {
3229
+ var point = this.convertCartesianToCartographic(cartesian3);
3230
+ point.id = id;
3231
+ this.quadTree.Insert(point);
3232
+ };
3233
+ /**
3234
+ * Calculates rough distance across earth between two points.
3235
+ * @param lon1
3236
+ * @param lat1
3237
+ * @param lon2
3238
+ * @param lat2
3239
+ * @returns
3240
+ */
3241
+ PointClustering.prototype.calculateDistance = function (lon1, lat1, lon2, lat2) {
3242
+ var lonDelta = Math.abs(lon1 - lon2);
3243
+ var latDelta = Math.abs(lat1 - lat2);
3244
+ // Approximate radius of the Earth in kilometers
3245
+ var earthRadius = 6371;
3246
+ var distance = 2 * Math.asin(Math.sqrt(Math.sin(latDelta / 2) * Math.sin(latDelta / 2) +
3247
+ Math.cos(lat1) * Math.cos(lat2) * Math.sin(lonDelta / 2) * Math.sin(lonDelta / 2))) * earthRadius;
3248
+ return distance;
3249
+ };
3250
+ /**
3251
+ * Adds entity to clustering logic.
3252
+ * Will return false if entity could not be clustered and therefor should not be hidden.
3253
+ * @param id
3254
+ * @param entity
3255
+ * @returns
3256
+ */
3257
+ PointClustering.prototype.AddEntity = function (id, entity) {
3258
+ if (this.disposed) {
3259
+ return false;
3260
+ }
3261
+ if (!entity) {
3262
+ return false;
3263
+ }
3264
+ if (entity.polygon || entity.polyline) {
3265
+ return false;
3266
+ }
3267
+ var pos3d = GetValue$1(this.viewer, entity.position);
3268
+ if (!(pos3d === null || pos3d === void 0 ? void 0 : pos3d.x)) {
3269
+ return false;
3270
+ }
3271
+ if (!this.pointColorBg && entity.point) {
3272
+ var pointColorBg = GetValue$1(this.viewer, entity.point.color);
3273
+ if (pointColorBg) {
3274
+ var cColor = null;
3275
+ if (pointColorBg instanceof Object) {
3276
+ cColor = new Cesium.Color(pointColorBg.red, pointColorBg.green, pointColorBg.blue, pointColorBg.alpha);
3277
+ }
3278
+ else if (typeof pointColorBg === "string") {
3279
+ cColor = Cesium.Color.fromCssColorString(pointColorBg);
3280
+ }
3281
+ // Determine if text color should instead be black based on background.
3282
+ // cColor contains r,g,b,a values where r,g,b are in the range [0,1].
3283
+ if (cColor) {
3284
+ var brightness = (cColor.red * 299 + cColor.green * 587 + cColor.blue * 114) / 1000;
3285
+ if (brightness > 0.5) {
3286
+ this.pointColorTxt = "black";
3287
+ }
3288
+ else {
3289
+ this.pointColorTxt = "white";
3290
+ }
3291
+ this.pointColorBg = cColor.toCssColorString();
3292
+ }
3293
+ }
3294
+ }
3295
+ if (!this.iconUrl && entity.billboard) {
3296
+ var iconUrl = GetValue$1(this.viewer, entity.billboard.image);
3297
+ if (typeof iconUrl == "string") {
3298
+ this.iconUrl = iconUrl;
3299
+ }
3300
+ }
3301
+ this.registeredEntityIds.add(id);
3302
+ this.addPoint(id, pos3d);
3303
+ this.updateQueue.Call();
3304
+ return true;
3305
+ };
3306
+ /**
3307
+ * Removes entity from clustering logic.
3308
+ * Warning: This will not reveal the entity, suppressShow will remain true.
3309
+ * This is made with the assumption that the entity is being removed from viewer.
3310
+ * @param id
3311
+ * @returns
3312
+ */
3313
+ PointClustering.prototype.RemoveEntity = function (id) {
3314
+ if (this.disposed) {
3315
+ return;
3316
+ }
3317
+ var pointToRemove = this.quadTree.Find(id);
3318
+ if (pointToRemove) {
3319
+ this.quadTree.Remove(pointToRemove);
3320
+ this.updateQueue.Call();
3321
+ }
3322
+ this.registeredEntityIds.delete(id);
3323
+ };
3324
+ return PointClustering;
3325
+ }());
3326
+
2524
3327
  var BATCH_SIZE = 500;
2525
3328
  var CHECK_BATCH_SIZE = 250;
2526
3329
  (function (EntitiesRenderManager) {
@@ -2544,6 +3347,9 @@
2544
3347
  this.apiGetter = apiGetter;
2545
3348
  this.item = item;
2546
3349
  this.visualsManager = visualsManager;
3350
+ if (item.enableClustering) {
3351
+ this.clustering = new PointClustering(this.visualsManager, this.item.id);
3352
+ }
2547
3353
  }
2548
3354
  Object.defineProperty(Manager.prototype, "Disposed", {
2549
3355
  get: function () {
@@ -2554,7 +3360,7 @@
2554
3360
  });
2555
3361
  Manager.prototype.Init = function (params) {
2556
3362
  var _this = this;
2557
- var _a, _b, _c, _d, _e;
3363
+ var _a, _b, _c, _d, _e, _f, _g;
2558
3364
  if (this.disposed) {
2559
3365
  throw (new Error("This item is disposed."));
2560
3366
  }
@@ -2586,17 +3392,22 @@
2586
3392
  menuItemId: this.item.id,
2587
3393
  retainTagIds: tagsToRender
2588
3394
  });
3395
+ (_e = this.clustering) === null || _e === void 0 ? void 0 : _e.Dispose();
2589
3396
  }
2590
3397
  else {
2591
3398
  this.visualsManager.RemoveRegos({
2592
3399
  menuItemId: this.item.id
2593
3400
  });
3401
+ (_f = this.clustering) === null || _f === void 0 ? void 0 : _f.Dispose();
2594
3402
  return;
2595
3403
  }
3404
+ if (this.item.enableClustering) {
3405
+ this.clustering = new PointClustering(this.visualsManager, this.item.id);
3406
+ }
2596
3407
  var api = this.apiGetter.getApi();
2597
3408
  this.getter = this.sharedGetters.GetOrCreateFilterGetter({
2598
3409
  api: api,
2599
- attrFilter: (_e = this.item.BruceEntity.Filter) !== null && _e !== void 0 ? _e : {},
3410
+ attrFilter: (_g = this.item.BruceEntity.Filter) !== null && _g !== void 0 ? _g : {},
2600
3411
  batchSize: BATCH_SIZE,
2601
3412
  typeId: this.item.BruceEntity["EntityType.ID"],
2602
3413
  monitor: this.monitor,
@@ -2628,7 +3439,13 @@
2628
3439
  _this.entityCheckQueue.Call();
2629
3440
  });
2630
3441
  this.entityCheckQueue = new bruceModels.DelayQueue(function () {
2631
- _this.doEntityCheck(Object.keys(_this.renderedEntities));
3442
+ var _a;
3443
+ // Don't bother checking for zoom control changes if we only have 1 item.
3444
+ // We'll let Cesium handle hide/show at max zoom range.
3445
+ var shouldCheck = ((_a = _this.item) === null || _a === void 0 ? void 0 : _a.CameraZoomSettings) && _this.item.CameraZoomSettings.length > 1;
3446
+ if (shouldCheck) {
3447
+ _this.doEntityCheck(Object.keys(_this.renderedEntities));
3448
+ }
2632
3449
  }, 3000);
2633
3450
  };
2634
3451
  Manager.prototype.Dispose = function () {
@@ -2638,7 +3455,7 @@
2638
3455
  this.doDispose();
2639
3456
  };
2640
3457
  Manager.prototype.doDispose = function () {
2641
- var _a, _b, _c;
3458
+ var _a, _b, _c, _d;
2642
3459
  (_a = this.getterSub) === null || _a === void 0 ? void 0 : _a.call(this);
2643
3460
  this.getterSub = null;
2644
3461
  if (this.getter) {
@@ -2652,6 +3469,7 @@
2652
3469
  (_c = this.viewMonitorRemoval) === null || _c === void 0 ? void 0 : _c.call(this);
2653
3470
  clearInterval(this.renderQueueInterval);
2654
3471
  this.renderQueue = [];
3472
+ (_d = this.clustering) === null || _d === void 0 ? void 0 : _d.Dispose();
2655
3473
  };
2656
3474
  Manager.prototype.ReRender = function (params) {
2657
3475
  return __awaiter(this, void 0, void 0, function () {
@@ -2785,14 +3603,14 @@
2785
3603
  }
2786
3604
  };
2787
3605
  Manager.prototype.renderEntities = function (entities, force) {
2788
- var _a, _b, _c;
3606
+ var _a, _b, _c, _d;
2789
3607
  if (force === void 0) { force = false; }
2790
3608
  return __awaiter(this, void 0, void 0, function () {
2791
- var typeId_1, cEntities, i, entity, id, cEntity, visual, tagIds, e_3;
2792
- return __generator(this, function (_d) {
2793
- switch (_d.label) {
3609
+ var typeId_1, cEntities, i, entity, id, cEntity, visual, wasClustered, tagIds, rego, e_3;
3610
+ return __generator(this, function (_e) {
3611
+ switch (_e.label) {
2794
3612
  case 0:
2795
- _d.trys.push([0, 2, , 3]);
3613
+ _e.trys.push([0, 2, , 3]);
2796
3614
  if (this.disposed || this.viewer.isDestroyed()) {
2797
3615
  return [2 /*return*/];
2798
3616
  }
@@ -2810,7 +3628,7 @@
2810
3628
  force: force
2811
3629
  })];
2812
3630
  case 1:
2813
- cEntities = _d.sent();
3631
+ cEntities = _e.sent();
2814
3632
  if (this.disposed) {
2815
3633
  this.doDispose();
2816
3634
  return [2 /*return*/];
@@ -2826,17 +3644,20 @@
2826
3644
  menuItemId: this.item.id
2827
3645
  })) === null || _b === void 0 ? void 0 : _b.visual;
2828
3646
  if (!visual || visual != cEntity) {
3647
+ wasClustered = this.clustering ? this.clustering.AddEntity(id, cEntity) : false;
2829
3648
  tagIds = (_c = entity.Bruce) === null || _c === void 0 ? void 0 : _c["Layer.ID"];
3649
+ rego = {
3650
+ entityId: id,
3651
+ menuItemId: this.item.id,
3652
+ visual: cEntity,
3653
+ priority: 0,
3654
+ entityTypeId: entity.Bruce["EntityType.ID"],
3655
+ accountId: this.apiGetter.accountId,
3656
+ tagIds: tagIds ? [].concat(tagIds) : [],
3657
+ suppressShow: wasClustered
3658
+ };
2830
3659
  this.visualsManager.AddRego({
2831
- rego: {
2832
- entityId: id,
2833
- menuItemId: this.item.id,
2834
- visual: cEntity,
2835
- priority: 0,
2836
- entityTypeId: entity.Bruce["EntityType.ID"],
2837
- accountId: this.apiGetter.accountId,
2838
- tagIds: tagIds ? [].concat(tagIds) : []
2839
- }
3660
+ rego: rego
2840
3661
  });
2841
3662
  }
2842
3663
  }
@@ -2845,12 +3666,13 @@
2845
3666
  entityId: id,
2846
3667
  menuItemId: this.item.id
2847
3668
  });
3669
+ (_d = this.clustering) === null || _d === void 0 ? void 0 : _d.RemoveEntity(id);
2848
3670
  }
2849
3671
  }
2850
3672
  this.viewer.scene.requestRender();
2851
3673
  return [3 /*break*/, 3];
2852
3674
  case 2:
2853
- e_3 = _d.sent();
3675
+ e_3 = _e.sent();
2854
3676
  console.error(e_3);
2855
3677
  return [3 /*break*/, 3];
2856
3678
  case 3: return [2 /*return*/];
@@ -3736,7 +4558,7 @@
3736
4558
  for (var i = 0; i < regos.length; i++) {
3737
4559
  var rego = regos[i];
3738
4560
  rego.best = rego === highestPriority;
3739
- updateEntityShow(viewer, rego.visual, getShowState(rego));
4561
+ updateEntityShow(viewer, rego.visual, rego.suppressShow ? false : getShowState(rego));
3740
4562
  }
3741
4563
  }
3742
4564
  function markEntity(register, rego, visual, ignoreParent) {
@@ -3928,6 +4750,17 @@
3928
4750
  enumerable: false,
3929
4751
  configurable: true
3930
4752
  });
4753
+ Register.prototype.ForceUpdate = function (params) {
4754
+ var entityIds = params.entityIds;
4755
+ for (var i = 0; i < entityIds.length; i++) {
4756
+ var entityId = entityIds[i];
4757
+ updateEntity(this.viewer, entityId, this);
4758
+ this.OnUpdate.Trigger({
4759
+ type: EVisualUpdateType.Update,
4760
+ entityId: entityId
4761
+ });
4762
+ }
4763
+ };
3931
4764
  Register.prototype.SetSelectionColor = function (color) {
3932
4765
  this.selectionColor = color;
3933
4766
  };
@@ -4445,6 +5278,9 @@
4445
5278
  this.monitor = monitor;
4446
5279
  this.item = item;
4447
5280
  this.visualsManager = visualsManager;
5281
+ if (this.item.enableClustering) {
5282
+ this.clustering = new PointClustering(visualsManager, this.item.id);
5283
+ }
4448
5284
  }
4449
5285
  Object.defineProperty(Manager.prototype, "Disposed", {
4450
5286
  get: function () {
@@ -4465,7 +5301,7 @@
4465
5301
  this.getter.Start();
4466
5302
  };
4467
5303
  Manager.prototype.Dispose = function () {
4468
- var _a;
5304
+ var _a, _b;
4469
5305
  if (this.disposed) {
4470
5306
  return;
4471
5307
  }
@@ -4475,6 +5311,7 @@
4475
5311
  this.visualsManager.RemoveRegos({
4476
5312
  menuItemId: this.item.id
4477
5313
  });
5314
+ (_b = this.clustering) === null || _b === void 0 ? void 0 : _b.Dispose();
4478
5315
  };
4479
5316
  Manager.prototype.ReRender = function (params) {
4480
5317
  return __awaiter(this, void 0, void 0, function () {
@@ -4543,19 +5380,19 @@
4543
5380
  });
4544
5381
  };
4545
5382
  Manager.prototype.renderEntities = function (entities, force) {
4546
- var _a;
5383
+ var _a, _b;
4547
5384
  if (force === void 0) { force = false; }
4548
5385
  return __awaiter(this, void 0, void 0, function () {
4549
- var cEntities, i, entity, id, cEntity, visual, e_2;
4550
- return __generator(this, function (_b) {
4551
- switch (_b.label) {
5386
+ var cEntities, i, entity, id, cEntity, visual, clustered, e_2;
5387
+ return __generator(this, function (_c) {
5388
+ switch (_c.label) {
4552
5389
  case 0:
4553
5390
  if (this.disposed || this.viewer.isDestroyed()) {
4554
5391
  return [2 /*return*/];
4555
5392
  }
4556
- _b.label = 1;
5393
+ _c.label = 1;
4557
5394
  case 1:
4558
- _b.trys.push([1, 3, , 4]);
5395
+ _c.trys.push([1, 3, , 4]);
4559
5396
  return [4 /*yield*/, exports.EntityRenderEngine.Render({
4560
5397
  viewer: this.viewer,
4561
5398
  apiGetter: this.apiGetter,
@@ -4566,7 +5403,7 @@
4566
5403
  force: force
4567
5404
  })];
4568
5405
  case 2:
4569
- cEntities = _b.sent();
5406
+ cEntities = _c.sent();
4570
5407
  for (i = 0; i < entities.length; i++) {
4571
5408
  entity = entities[i];
4572
5409
  id = entity.Bruce.ID;
@@ -4578,6 +5415,7 @@
4578
5415
  menuItemId: this.item.id
4579
5416
  })) === null || _a === void 0 ? void 0 : _a.visual;
4580
5417
  if (!visual || visual != cEntity) {
5418
+ clustered = this.clustering ? this.clustering.AddEntity(id, cEntity) : false;
4581
5419
  this.visualsManager.AddRego({
4582
5420
  rego: {
4583
5421
  entityId: id,
@@ -4585,7 +5423,8 @@
4585
5423
  visual: cEntity,
4586
5424
  priority: 0,
4587
5425
  entityTypeId: entity.Bruce["EntityType.ID"],
4588
- accountId: this.apiGetter.accountId
5426
+ accountId: this.apiGetter.accountId,
5427
+ suppressShow: clustered
4589
5428
  }
4590
5429
  });
4591
5430
  }
@@ -4595,12 +5434,13 @@
4595
5434
  entityId: id,
4596
5435
  menuItemId: this.item.id
4597
5436
  });
5437
+ (_b = this.clustering) === null || _b === void 0 ? void 0 : _b.RemoveEntity(id);
4598
5438
  }
4599
5439
  }
4600
5440
  this.viewer.scene.requestRender();
4601
5441
  return [3 /*break*/, 4];
4602
5442
  case 3:
4603
- e_2 = _b.sent();
5443
+ e_2 = _c.sent();
4604
5444
  console.error(e_2);
4605
5445
  return [3 /*break*/, 4];
4606
5446
  case 4: return [2 /*return*/];
@@ -9939,7 +10779,7 @@
9939
10779
  ViewRenderEngine.Render = Render;
9940
10780
  })(exports.ViewRenderEngine || (exports.ViewRenderEngine = {}));
9941
10781
 
9942
- var VERSION = "2.1.3";
10782
+ var VERSION = "2.1.9";
9943
10783
 
9944
10784
  exports.VERSION = VERSION;
9945
10785
  exports.CesiumViewMonitor = CesiumViewMonitor;