bruce-cesium 3.7.3 → 3.7.4

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.
@@ -1,6 +1,6 @@
1
1
  import { BruceEvent, Cartes, Carto, Entity as Entity$1, Geometry, Tileset, MathUtils, LRUCache, ProjectViewTile, DelayQueue, ZoomControl, Style, EntityTag, Calculator, EntityLod, EntityType, ClientFile, ObjectUtils, Bounds, Api, EntityRelationType, ENVIRONMENT, EntityCoords, EntitySource, MenuItem, EntityRelation, ProgramKey, AbstractApi, ProjectViewBookmark, EntityAttachment, EntityAttachmentType, EntityAttribute, ProjectView, ProjectViewLegacyTile, Camera } from 'bruce-models';
2
2
  import * as Cesium from 'cesium';
3
- import { Cartographic, Cartesian2, Math as Math$1, Cartesian3, CallbackProperty, Color, HeightReference, Rectangle, JulianDate, SceneMode, Entity, Primitive, Cesium3DTileFeature, GeoJsonDataSource, ColorMaterialProperty, ConstantProperty, DistanceDisplayCondition, NearFarScalar, Model, HorizontalOrigin, VerticalOrigin, ClassificationType, ArcType, CornerType, ShadowMode, PolygonHierarchy, PolylineGraphics, HeadingPitchRoll, Transforms, ColorBlendMode, Cesium3DTileColorBlendMode, HeadingPitchRange, Ion, Cesium3DTileStyle, KmlDataSource, SceneTransforms, OrthographicFrustum, EasingFunction, EllipsoidTerrainProvider, BingMapsImageryProvider, BingMapsStyle, MapboxImageryProvider, MapboxStyleImageryProvider, ArcGisMapServerImageryProvider, OpenStreetMapImageryProvider, GridImageryProvider, GeographicTilingScheme, ImageryLayer, UrlTemplateImageryProvider, TileMapServiceImageryProvider, IonImageryProvider, CesiumTerrainProvider, Cesium3DTileset, Matrix4, Matrix3, IonResource, CesiumInspector, defined, ClockRange, EllipsoidGeodesic, sampleTerrainMostDetailed, PolygonPipeline, BoundingSphere, GeometryInstance, ScreenSpaceEventHandler, ScreenSpaceEventType, ModelGraphics, PolygonGraphics, CorridorGraphics, PointGraphics, BillboardGraphics, EllipseGraphics, CzmlDataSource, Quaternion, ConstantPositionProperty, Intersect } from 'cesium';
3
+ import { Cartographic, Cartesian2, Math as Math$1, Cartesian3, CallbackProperty, Color, HeightReference, Rectangle, JulianDate, DistanceDisplayCondition, NearFarScalar, Model, Entity, HorizontalOrigin, VerticalOrigin, ConstantProperty, ConstantPositionProperty, ClassificationType, ArcType, CornerType, ShadowMode, PolygonHierarchy, PolylineGraphics, ColorMaterialProperty, HeadingPitchRoll, Transforms, ColorBlendMode, Primitive, Cesium3DTileFeature, SceneMode, GeoJsonDataSource, Cesium3DTileColorBlendMode, HeadingPitchRange, Ion, Cesium3DTileStyle, KmlDataSource, SceneTransforms, OrthographicFrustum, EasingFunction, Cesium3DTileset, Matrix4, Matrix3, IonResource, EllipsoidTerrainProvider, CesiumInspector, defined, ClockRange, BingMapsImageryProvider, BingMapsStyle, MapboxImageryProvider, MapboxStyleImageryProvider, ArcGisMapServerImageryProvider, OpenStreetMapImageryProvider, GridImageryProvider, GeographicTilingScheme, ImageryLayer, UrlTemplateImageryProvider, TileMapServiceImageryProvider, IonImageryProvider, CesiumTerrainProvider, EllipsoidGeodesic, sampleTerrainMostDetailed, PolygonPipeline, BoundingSphere, GeometryInstance, ModelGraphics, PolygonGraphics, CorridorGraphics, PointGraphics, BillboardGraphics, EllipseGraphics, ScreenSpaceEventHandler, ScreenSpaceEventType, CzmlDataSource, Quaternion, Intersect } from 'cesium';
4
4
 
5
5
  /*! *****************************************************************************
6
6
  Copyright (c) Microsoft Corporation. All rights reserved.
@@ -900,6 +900,282 @@ var DrawingUtils;
900
900
  DrawingUtils.RaisePos3d = RaisePos3d;
901
901
  })(DrawingUtils || (DrawingUtils = {}));
902
902
 
903
+ function getColor(viewer, obj) {
904
+ var value = null;
905
+ if (obj === null || obj === void 0 ? void 0 : obj.getValue) {
906
+ var date = viewer.scene.lastRenderTime;
907
+ if (!date) {
908
+ date = viewer.clock.currentTime;
909
+ }
910
+ value = obj.getValue(date);
911
+ }
912
+ else {
913
+ value = obj;
914
+ }
915
+ if (value && value instanceof ColorMaterialProperty) {
916
+ value = value.color;
917
+ }
918
+ return value;
919
+ }
920
+ function getNumber(viewer, obj) {
921
+ var value = null;
922
+ if (obj === null || obj === void 0 ? void 0 : obj.getValue) {
923
+ var date = viewer.scene.lastRenderTime;
924
+ if (!date) {
925
+ date = viewer.clock.currentTime;
926
+ }
927
+ value = obj.getValue(date);
928
+ }
929
+ else {
930
+ value = obj;
931
+ }
932
+ return value;
933
+ }
934
+ /**
935
+ * Returns if a given visual is alive and in the scene.
936
+ * @param viewer
937
+ * @param visual
938
+ * @returns
939
+ */
940
+ function isFeatureAlive(viewer, feature) {
941
+ if (!(viewer === null || viewer === void 0 ? void 0 : viewer.scene) || viewer.isDestroyed()) {
942
+ return false;
943
+ }
944
+ var cTileset = feature === null || feature === void 0 ? void 0 : feature.tileset;
945
+ if (!cTileset) {
946
+ return false;
947
+ }
948
+ if (cTileset.isDestroyed() || !viewer.scene.primitives.contains(cTileset)) {
949
+ return false;
950
+ }
951
+ return true;
952
+ }
953
+ var _lastMark = 0;
954
+ var generateMark = function () {
955
+ _lastMark += 1;
956
+ return _lastMark;
957
+ };
958
+ function setMark(color, mark) {
959
+ color["NEXTSPACE_PROPERTY_MARK"] = mark;
960
+ }
961
+ function assertColorMark(mark, color) {
962
+ return color["NEXTSPACE_PROPERTY_MARK"] == mark;
963
+ }
964
+ var CesiumAnimatedProperty;
965
+ (function (CesiumAnimatedProperty) {
966
+ /**
967
+ * Example:
968
+ * ```
969
+ * const myEntity = null; // Get an Entity from somewhere.
970
+ *
971
+ * const animateColor = new AnimateColor({
972
+ * viewer: viewer,
973
+ * color: Cesium.Color.RED,
974
+ * startColor: myEntity.model.color,
975
+ * type: "LINEAR",
976
+ * durationMs: 1000
977
+ * });
978
+ *
979
+ * myEntity.model.color = new Cesium.CallbackProperty(() => {
980
+ * return animateColor.GetValue();
981
+ * }, false);
982
+ * ```
983
+ */
984
+ var AnimateColor = /** @class */ (function () {
985
+ function AnimateColor(params) {
986
+ var _a;
987
+ this.viewer = params.viewer;
988
+ this.color = params.color;
989
+ this.durationMs = params.durationMs;
990
+ this.startColor = getColor(this.viewer, params.startColor);
991
+ if ((_a = this.startColor) === null || _a === void 0 ? void 0 : _a.clone) {
992
+ this.startColor = this.startColor.clone();
993
+ }
994
+ if (!this.startColor) {
995
+ this.startColor = Color.WHITE.clone();
996
+ console.warn("No start color provided. Using WHITE as start color. Animation may not work as expected.");
997
+ }
998
+ this.startTime = new Date();
999
+ }
1000
+ /**
1001
+ * Returns the calculated color at the provided time.
1002
+ * @returns
1003
+ */
1004
+ AnimateColor.prototype.GetColor = function () {
1005
+ var now = new Date();
1006
+ var elapsedMs = now.getTime() - this.startTime.getTime();
1007
+ // Animation over.
1008
+ if (elapsedMs >= this.durationMs) {
1009
+ return this.color;
1010
+ }
1011
+ try {
1012
+ var progress = elapsedMs / this.durationMs;
1013
+ return Color.lerp(this.startColor, this.color, progress, new Color());
1014
+ }
1015
+ catch (e) {
1016
+ console.error(e);
1017
+ }
1018
+ // Failed to calculate color.
1019
+ // We'll just return the target color.
1020
+ return this.color;
1021
+ };
1022
+ /**
1023
+ * Returns the calculated color as a material property.
1024
+ * @returns
1025
+ */
1026
+ AnimateColor.prototype.GetMaterial = function () {
1027
+ var color = this.GetColor();
1028
+ return new ColorMaterialProperty(color);
1029
+ };
1030
+ return AnimateColor;
1031
+ }());
1032
+ CesiumAnimatedProperty.AnimateColor = AnimateColor;
1033
+ var AnimateNumber = /** @class */ (function () {
1034
+ function AnimateNumber(params) {
1035
+ this.paused = false;
1036
+ this.paused = Boolean(params.startPaused);
1037
+ this.viewer = params.viewer;
1038
+ this.value = params.value;
1039
+ this.durationMs = params.durationMs;
1040
+ this.startValue = getNumber(this.viewer, params.startValue);
1041
+ if (!this.startValue) {
1042
+ this.startValue = 0;
1043
+ }
1044
+ if (!this.paused) {
1045
+ this.startTime = new Date();
1046
+ }
1047
+ }
1048
+ AnimateNumber.prototype.Play = function () {
1049
+ if (this.paused) {
1050
+ this.paused = false;
1051
+ this.startTime = new Date();
1052
+ }
1053
+ };
1054
+ AnimateNumber.prototype.GetValue = function () {
1055
+ if (this.paused) {
1056
+ return this.startValue;
1057
+ }
1058
+ var now = new Date();
1059
+ var elapsedMs = now.getTime() - this.startTime.getTime();
1060
+ // Animation over.
1061
+ if (elapsedMs >= this.durationMs) {
1062
+ return this.value;
1063
+ }
1064
+ try {
1065
+ var progress = elapsedMs / this.durationMs;
1066
+ return Math$1.lerp(this.startValue, this.value, progress);
1067
+ }
1068
+ catch (e) {
1069
+ console.error(e);
1070
+ }
1071
+ // Failed to calculate value.
1072
+ // We'll just return the target value.
1073
+ return this.value;
1074
+ };
1075
+ return AnimateNumber;
1076
+ }());
1077
+ CesiumAnimatedProperty.AnimateNumber = AnimateNumber;
1078
+ /**
1079
+ * Animates the color of a feature.
1080
+ * This is handled separately from the AnimateColor class as Tileset features do not support Cesium callback properties.
1081
+ *
1082
+ * Example:
1083
+ * ```
1084
+ * const animateColor = AnimateTFeatureColor({
1085
+ * viewer: viewer,
1086
+ * feature: feature,
1087
+ * color: Cesium.Color.RED,
1088
+ * startColor: feature.color,
1089
+ * durationMs: 1000
1090
+ * });
1091
+ * ```
1092
+ * @param params
1093
+ * @returns
1094
+ */
1095
+ function AnimateTFeatureColor(params) {
1096
+ var viewer = params.viewer, feature = params.feature, color = params.color, startColor = params.startColor, durationMs = params.durationMs;
1097
+ ClearTFeatureColorAnimation(feature);
1098
+ if (!startColor) {
1099
+ if (feature.color) {
1100
+ startColor = feature.color;
1101
+ if (startColor.clone) {
1102
+ startColor = startColor.clone();
1103
+ }
1104
+ }
1105
+ else {
1106
+ startColor = Color.WHITE.clone();
1107
+ }
1108
+ }
1109
+ // Don't animate if the colour is the same.
1110
+ var curColor = getColor(viewer, feature.color);
1111
+ if (curColor && Color.WHITE.equals(curColor)) {
1112
+ curColor = null;
1113
+ }
1114
+ var colorTmp = color == null || Color.WHITE.equals(color) ? null : color;
1115
+ if (!curColor && !colorTmp) {
1116
+ return function () { };
1117
+ }
1118
+ else if (curColor && colorTmp && curColor.equals(colorTmp)) {
1119
+ return function () { };
1120
+ }
1121
+ // Marks are used to detect external changes to the feature's color.
1122
+ // If an external change is detected, the animation will stop.
1123
+ var mark = generateMark();
1124
+ setMark(feature.color, mark);
1125
+ setMark(startColor, mark);
1126
+ setMark(color, mark);
1127
+ var startTime = new Date();
1128
+ var removal = viewer.scene.postUpdate.addEventListener(function () {
1129
+ if (!isFeatureAlive(viewer, feature)) {
1130
+ removal === null || removal === void 0 ? void 0 : removal();
1131
+ removal = null;
1132
+ return;
1133
+ }
1134
+ if (!assertColorMark(mark, feature.color)) {
1135
+ removal === null || removal === void 0 ? void 0 : removal();
1136
+ removal = null;
1137
+ return;
1138
+ }
1139
+ var now = new Date();
1140
+ var elapsedMs = now.getTime() - startTime.getTime();
1141
+ // Animation over.
1142
+ if (elapsedMs >= durationMs) {
1143
+ feature.color = color;
1144
+ removal === null || removal === void 0 ? void 0 : removal();
1145
+ removal = null;
1146
+ return;
1147
+ }
1148
+ try {
1149
+ var progress = elapsedMs / durationMs;
1150
+ var newColor = Color.lerp(startColor, color, progress, new Color());
1151
+ setMark(newColor, mark);
1152
+ feature.color = newColor;
1153
+ return;
1154
+ }
1155
+ catch (e) {
1156
+ console.error(e);
1157
+ }
1158
+ // Failed to calculate color.
1159
+ // We'll just set the target color and stop the animation.
1160
+ feature.color = color;
1161
+ });
1162
+ // Return a function to stop the animation.
1163
+ feature["ANIMATED_COLOR_REMOVAL"] = removal;
1164
+ return function () {
1165
+ removal === null || removal === void 0 ? void 0 : removal();
1166
+ removal = null;
1167
+ };
1168
+ }
1169
+ CesiumAnimatedProperty.AnimateTFeatureColor = AnimateTFeatureColor;
1170
+ function ClearTFeatureColorAnimation(feature) {
1171
+ if (feature && feature["ANIMATED_COLOR_REMOVAL"]) {
1172
+ feature["ANIMATED_COLOR_REMOVAL"]();
1173
+ feature["ANIMATED_COLOR_REMOVAL"] = null;
1174
+ }
1175
+ }
1176
+ CesiumAnimatedProperty.ClearTFeatureColorAnimation = ClearTFeatureColorAnimation;
1177
+ })(CesiumAnimatedProperty || (CesiumAnimatedProperty = {}));
1178
+
903
1179
  /**
904
1180
  * Returns if a given visual can be styled by this utility.
905
1181
  * @param viewer
@@ -1020,7 +1296,7 @@ function storeColor(viewer, key, color, graphic) {
1020
1296
  * @param graphic
1021
1297
  * @returns
1022
1298
  */
1023
- function getColor(viewer, key, graphic) {
1299
+ function getColor$1(viewer, key, graphic) {
1024
1300
  var color = graphic[getStoreKey(key)];
1025
1301
  // If no color is stored for the default color, we'll calculate and store it.
1026
1302
  if (!color) {
@@ -1050,6 +1326,8 @@ function getColor(viewer, key, graphic) {
1050
1326
  function applyOpacity(viewer, opacity, graphic) {
1051
1327
  refreshColor(viewer, graphic, opacity);
1052
1328
  }
1329
+ var ANIMATE_COLOR_MS = 200;
1330
+ var ANIMATE_COLOR_HIGHLIGHT_MS = 200;
1053
1331
  /**
1054
1332
  * Applies a color to a graphic based on the current key states.
1055
1333
  * Eg: if the graphic is selected, it will apply the selected color.
@@ -1058,7 +1336,7 @@ function applyOpacity(viewer, opacity, graphic) {
1058
1336
  * @param opacity
1059
1337
  */
1060
1338
  function refreshColor(viewer, graphic, opacity) {
1061
- var _a;
1339
+ var _a, _b;
1062
1340
  // Calculate what color key we should apply.
1063
1341
  var key = "default";
1064
1342
  if (getKeyState(graphic, "select")) {
@@ -1069,11 +1347,12 @@ function refreshColor(viewer, graphic, opacity) {
1069
1347
  }
1070
1348
  // This ensures that the default color is always stored prior to applying a new color.
1071
1349
  if (key != "default") {
1072
- getColor(viewer, "default", graphic);
1350
+ getColor$1(viewer, "default", graphic);
1073
1351
  }
1074
- var color = (_a = getColor(viewer, key, graphic)) !== null && _a !== void 0 ? _a : Color.WHITE;
1352
+ var color = (_a = getColor$1(viewer, key, graphic)) !== null && _a !== void 0 ? _a : Color.WHITE;
1075
1353
  // If we're highlighting and it's selected, don't change the color.
1076
1354
  if (key != "highlight" || getKeyState(graphic, "select") == false) {
1355
+ var animateMs = key == "highlight" ? ANIMATE_COLOR_HIGHLIGHT_MS : ANIMATE_COLOR_MS;
1077
1356
  color = color.clone();
1078
1357
  // Multiply opacity if one is set.
1079
1358
  if (opacity != null) {
@@ -1089,10 +1368,34 @@ function refreshColor(viewer, graphic, opacity) {
1089
1368
  }
1090
1369
  }
1091
1370
  if (graphic instanceof Cesium3DTileFeature) {
1092
- graphic.color = color;
1371
+ CesiumAnimatedProperty.ClearTFeatureColorAnimation(graphic);
1372
+ if (key == "default") {
1373
+ graphic.color = color;
1374
+ }
1375
+ else {
1376
+ CesiumAnimatedProperty.AnimateTFeatureColor({
1377
+ color: color.clone(),
1378
+ durationMs: animateMs,
1379
+ feature: graphic,
1380
+ viewer: viewer,
1381
+ startColor: ((_b = graphic.color) === null || _b === void 0 ? void 0 : _b.clone) ? graphic.color.clone() : graphic.color
1382
+ });
1383
+ }
1093
1384
  }
1094
1385
  else if (graphic instanceof ModelGraphics) {
1095
- graphic.color = new ConstantProperty(color);
1386
+ // graphic.color = new Cesium.ConstantProperty(color);
1387
+ var animateColor_1 = new CesiumAnimatedProperty.AnimateColor({
1388
+ color: color,
1389
+ durationMs: animateMs,
1390
+ viewer: viewer,
1391
+ startColor: graphic.color
1392
+ });
1393
+ if (graphic.color instanceof CallbackProperty) {
1394
+ graphic.color.setCallback(function () { return animateColor_1.GetColor(); }, false);
1395
+ }
1396
+ else {
1397
+ graphic.color = new CallbackProperty(function () { return animateColor_1.GetColor(); }, false);
1398
+ }
1096
1399
  }
1097
1400
  else if (graphic instanceof PolygonGraphics) {
1098
1401
  graphic.material = new ColorMaterialProperty(color);
@@ -1104,10 +1407,34 @@ function refreshColor(viewer, graphic, opacity) {
1104
1407
  graphic.material = new ColorMaterialProperty(color);
1105
1408
  }
1106
1409
  else if (graphic instanceof PointGraphics) {
1107
- graphic.color = new ConstantProperty(color);
1410
+ // graphic.color = new Cesium.ConstantProperty(color);
1411
+ var animateColor_2 = new CesiumAnimatedProperty.AnimateColor({
1412
+ color: color,
1413
+ durationMs: animateMs,
1414
+ viewer: viewer,
1415
+ startColor: graphic.color
1416
+ });
1417
+ if (graphic.color instanceof CallbackProperty) {
1418
+ graphic.color.setCallback(function () { return animateColor_2.GetColor(); }, false);
1419
+ }
1420
+ else {
1421
+ graphic.color = new CallbackProperty(function () { return animateColor_2.GetColor(); }, false);
1422
+ }
1108
1423
  }
1109
1424
  else if (graphic instanceof BillboardGraphics) {
1110
- graphic.color = new ConstantProperty(color);
1425
+ // graphic.color = new Cesium.ConstantProperty(color);
1426
+ var animateColor_3 = new CesiumAnimatedProperty.AnimateColor({
1427
+ color: color,
1428
+ durationMs: animateMs,
1429
+ viewer: viewer,
1430
+ startColor: graphic.color
1431
+ });
1432
+ if (graphic.color instanceof CallbackProperty) {
1433
+ graphic.color.setCallback(function () { return animateColor_3.GetColor(); }, false);
1434
+ }
1435
+ else {
1436
+ graphic.color = new CallbackProperty(function () { return animateColor_3.GetColor(); }, false);
1437
+ }
1111
1438
  }
1112
1439
  else if (graphic instanceof EllipseGraphics) {
1113
1440
  graphic.material = new ColorMaterialProperty(color);
@@ -1208,6 +1535,64 @@ var CesiumEntityStyler;
1208
1535
  }
1209
1536
  }
1210
1537
  CesiumEntityStyler.Refresh = Refresh;
1538
+ function BakeDefaultColor(params) {
1539
+ var viewer = params.viewer, entity = params.entity, override = params.override;
1540
+ if (!entity) {
1541
+ return;
1542
+ }
1543
+ var parts = EntityUtils.GatherEntity({
1544
+ entity: entity
1545
+ });
1546
+ for (var i = 0; i < parts.length; i++) {
1547
+ var part = parts[i];
1548
+ if (!isAlive(viewer, part)) {
1549
+ continue;
1550
+ }
1551
+ // If we're not overriding then we check to ensure a colour is not already set.
1552
+ if (override == false) {
1553
+ var stored = part[getStoreKey("default")];
1554
+ if (stored) {
1555
+ continue;
1556
+ }
1557
+ }
1558
+ if (part instanceof Cesium3DTileFeature) {
1559
+ var opacity = getAppliedOpacity(part);
1560
+ storeColor(viewer, "default", calculateCurColor(viewer, part), part);
1561
+ refreshColor(viewer, part, opacity);
1562
+ }
1563
+ else if (part instanceof Entity) {
1564
+ if (part.billboard) {
1565
+ storeColor(viewer, "default", calculateCurColor(viewer, part.billboard), part.billboard);
1566
+ refreshColor(viewer, part.billboard, getAppliedOpacity(part.billboard));
1567
+ }
1568
+ if (part.model) {
1569
+ storeColor(viewer, "default", calculateCurColor(viewer, part.model), part.model);
1570
+ refreshColor(viewer, part.model, getAppliedOpacity(part.model));
1571
+ }
1572
+ if (part.polyline) {
1573
+ storeColor(viewer, "default", calculateCurColor(viewer, part.polyline), part.polyline);
1574
+ refreshColor(viewer, part.polyline, getAppliedOpacity(part.polyline));
1575
+ }
1576
+ if (part.polygon) {
1577
+ storeColor(viewer, "default", calculateCurColor(viewer, part.polygon), part.polygon);
1578
+ refreshColor(viewer, part.polygon, getAppliedOpacity(part.polygon));
1579
+ }
1580
+ if (part.corridor) {
1581
+ storeColor(viewer, "default", calculateCurColor(viewer, part.corridor), part.corridor);
1582
+ refreshColor(viewer, part.corridor, getAppliedOpacity(part.corridor));
1583
+ }
1584
+ if (part.point) {
1585
+ storeColor(viewer, "default", calculateCurColor(viewer, part.point), part.point);
1586
+ refreshColor(viewer, part.point, getAppliedOpacity(part.point));
1587
+ }
1588
+ if (part.ellipse) {
1589
+ storeColor(viewer, "default", calculateCurColor(viewer, part.ellipse), part.ellipse);
1590
+ refreshColor(viewer, part.ellipse, getAppliedOpacity(part.ellipse));
1591
+ }
1592
+ }
1593
+ }
1594
+ }
1595
+ CesiumEntityStyler.BakeDefaultColor = BakeDefaultColor;
1211
1596
  /**
1212
1597
  * Updates the default colour of a graphic.
1213
1598
  * This will not change the graphic's state to use it if the entity is selected/highlighted.
@@ -4257,7 +4642,7 @@ var POINT_BILLBOARD_PADDING = 1;
4257
4642
  var createCircleBillboard = function (size, colorCss) {
4258
4643
  var key = size + "-" + colorCss;
4259
4644
  var cacheData = _billboardCache.Get(key);
4260
- if ((cacheData === null || cacheData === void 0 ? void 0 : cacheData.canvas) instanceof HTMLCanvasElement) {
4645
+ if ((cacheData === null || cacheData === void 0 ? void 0 : cacheData.canvasDataUri) && typeof (cacheData === null || cacheData === void 0 ? void 0 : cacheData.canvasDataUri) == "string") {
4261
4646
  return cacheData;
4262
4647
  }
4263
4648
  // Slight padding to avoid corners clipping.
@@ -4271,7 +4656,7 @@ var createCircleBillboard = function (size, colorCss) {
4271
4656
  context.fillStyle = colorCss;
4272
4657
  context.fill();
4273
4658
  var data = {
4274
- canvas: canvas,
4659
+ canvasDataUri: canvas.toDataURL("image/png"),
4275
4660
  colorCss: colorCss,
4276
4661
  size: size,
4277
4662
  height: canvasSize,
@@ -4306,7 +4691,7 @@ var createImageBillboard = function (url) {
4306
4691
  var context = canvas_1.getContext("2d");
4307
4692
  context.drawImage(image_1, 0, 0);
4308
4693
  var data = {
4309
- canvas: canvas_1,
4694
+ canvasDataUri: canvas_1.toDataURL("image/png"),
4310
4695
  height: image_1.height
4311
4696
  };
4312
4697
  res(data);
@@ -4424,7 +4809,7 @@ var EntityRenderEngine;
4424
4809
  function Render(params) {
4425
4810
  var _a, _b, _c, _d, _e, _f, _g, _h;
4426
4811
  return __awaiter(this, void 0, void 0, function () {
4427
- var groupRenderParams, i, entity, geometry, cEntities, models, multiGeometry, polygons, polylines, points, i, entity, id, zoomItem, displayType, newRenderId, existingRego, oldRenderId, mParams, mEntities, i, entity, id, cEntity, _loop_1, i, pParams, pEntities, i, entity, cEntity, pParams, pEntities, i, entity, cEntity, pParams, pEntities, i, entity, cEntity;
4812
+ var groupRenderParams, i, entity, geometry, cEntities, models, multiGeometry, polygons, polylines, points, i, entity, id, zoomItem, displayType, existingRego, newRenderId, oldRenderId, mParams, mEntities, i, entity, id, cEntity, _loop_1, i, pParams, pEntities, i, entity, cEntity, pParams, pEntities, i, entity, cEntity, pParams, pEntities, i, entity, cEntity;
4428
4813
  return __generator(this, function (_j) {
4429
4814
  switch (_j.label) {
4430
4815
  case 0:
@@ -4468,16 +4853,23 @@ var EntityRenderEngine;
4468
4853
  displayType = ZoomControl.EDisplayType.Geometry;
4469
4854
  }
4470
4855
  if (displayType != ZoomControl.EDisplayType.Hidden) {
4471
- newRenderId = getRenderGroupId(zoomItem, (_b = params.viewer) === null || _b === void 0 ? void 0 : _b.terrainProvider);
4472
4856
  existingRego = params.visualRegister.GetRego({
4473
4857
  entityId: id,
4474
4858
  menuItemId: params.menuItemId
4475
4859
  });
4860
+ newRenderId = getRenderGroupId(zoomItem, (_b = params.viewer) === null || _b === void 0 ? void 0 : _b.terrainProvider);
4476
4861
  oldRenderId = (_c = existingRego === null || existingRego === void 0 ? void 0 : existingRego.visual) === null || _c === void 0 ? void 0 : _c._renderGroup;
4477
4862
  if (!params.force && newRenderId == oldRenderId && !(existingRego === null || existingRego === void 0 ? void 0 : existingRego.stale)) {
4863
+ // No sorting category needed. Already rendered the way we want.
4478
4864
  cEntities[id] = existingRego.visual;
4479
4865
  }
4480
4866
  else {
4867
+ // Add so we can re-use the graphic and update it.
4868
+ if (existingRego && newRenderId == oldRenderId) {
4869
+ cEntities[id] = existingRego.visual;
4870
+ // Flag as no longer stale as we're unlikely to recreate the rego if we're reusing the graphic.
4871
+ existingRego.stale = false;
4872
+ }
4481
4873
  if (displayType == ZoomControl.EDisplayType.Model3D) {
4482
4874
  models.push(entity);
4483
4875
  }
@@ -4497,7 +4889,7 @@ var EntityRenderEngine;
4497
4889
  }
4498
4890
  }
4499
4891
  if (!(models.length > 0)) return [3 /*break*/, 2];
4500
- mParams = __assign(__assign({}, groupRenderParams), { entities: models });
4892
+ mParams = __assign(__assign({}, groupRenderParams), { rendered: cEntities, entities: models });
4501
4893
  return [4 /*yield*/, Model3d.RenderGroup(mParams)];
4502
4894
  case 1:
4503
4895
  mEntities = _j.sent();
@@ -4525,7 +4917,7 @@ var EntityRenderEngine;
4525
4917
  polygons.push(entity);
4526
4918
  return [2 /*return*/, "continue"];
4527
4919
  }
4528
- pParams = __assign(__assign({}, groupRenderParams), { entities: [] });
4920
+ pParams = __assign(__assign({}, groupRenderParams), { entities: [], rendered: cEntities });
4529
4921
  zoomItem = pParams.zoomItems[entity.Bruce.ID];
4530
4922
  for (j = 0; j < entity.geometry.MultiGeometry.length; j++) {
4531
4923
  subEntity = __assign(__assign({}, entity), { geometry: entity.geometry.MultiGeometry[j], Bruce: __assign(__assign({}, entity.Bruce), { ID: ObjectUtils.UId() }) });
@@ -4594,7 +4986,7 @@ var EntityRenderEngine;
4594
4986
  return [3 /*break*/, 3];
4595
4987
  case 6:
4596
4988
  if (!(polygons.length > 0)) return [3 /*break*/, 8];
4597
- pParams = __assign(__assign({}, groupRenderParams), { entities: polygons });
4989
+ pParams = __assign(__assign({}, groupRenderParams), { entities: polygons, rendered: cEntities });
4598
4990
  return [4 /*yield*/, Polygon.RenderGroup(pParams)];
4599
4991
  case 7:
4600
4992
  pEntities = _j.sent();
@@ -4611,7 +5003,7 @@ var EntityRenderEngine;
4611
5003
  _j.label = 8;
4612
5004
  case 8:
4613
5005
  if (!(polylines.length > 0)) return [3 /*break*/, 10];
4614
- pParams = __assign(__assign({}, groupRenderParams), { entities: polylines });
5006
+ pParams = __assign(__assign({}, groupRenderParams), { entities: polylines, rendered: cEntities });
4615
5007
  return [4 /*yield*/, Polyline.RenderGroup(pParams)];
4616
5008
  case 9:
4617
5009
  pEntities = _j.sent();
@@ -4628,7 +5020,7 @@ var EntityRenderEngine;
4628
5020
  _j.label = 10;
4629
5021
  case 10:
4630
5022
  if (!(points.length > 0)) return [3 /*break*/, 12];
4631
- pParams = __assign(__assign({}, groupRenderParams), { entities: points });
5023
+ pParams = __assign(__assign({}, groupRenderParams), { entities: points, rendered: cEntities });
4632
5024
  return [4 /*yield*/, Point.RenderGroup(pParams)];
4633
5025
  case 11:
4634
5026
  pEntities = _j.sent();
@@ -4692,11 +5084,11 @@ var EntityRenderEngine;
4692
5084
  }
4693
5085
  Point.CreateCircleBillboard = CreateCircleBillboard;
4694
5086
  function Render(params) {
4695
- var _a, _b;
5087
+ var _a, _b, _c, _d;
4696
5088
  return __awaiter(this, void 0, void 0, function () {
4697
- var entity, style, type, cEntity, siblings, iconUrlRows, icon, iconUrl, metadata, api, image, e_5, iconScale, disableDepthTest, bColor, cColor, heightRef, radius, bFill, cFill, outline, cOutline, outlineWidth, bOutline, heightRef, pos3d, extrusion, outlineExtrusion, bColor, cColor, size, heightRef, circleBillboard, disableDepthTest;
4698
- return __generator(this, function (_c) {
4699
- switch (_c.label) {
5089
+ var entity, style, type, cEntity, siblings, prepareExistingGraphic, iconUrlRows, icon, iconUrl, metadata, api, image, e_5, iconScale, disableDepthTest, bColor, cColor_1, heightRef, currentImgKey, radius, bFill, cFill, outline, cOutline, outlineWidth, bOutline, heightRef, pos3d, extrusion, hasOutline, outlineExtrusion, outlineEntity, bColor, cColor, size, heightRef, circleBillboard, disableDepthTest, imgKey, currentImgKey;
5090
+ return __generator(this, function (_e) {
5091
+ switch (_e.label) {
4700
5092
  case 0:
4701
5093
  entity = params.entity;
4702
5094
  style = params.style;
@@ -4709,6 +5101,27 @@ var EntityRenderEngine;
4709
5101
  }
4710
5102
  cEntity = null;
4711
5103
  siblings = [];
5104
+ prepareExistingGraphic = function (cEntity, siblings) {
5105
+ if (siblings === void 0) { siblings = 0; }
5106
+ // Gather entity in case previous version had sibling graphics we no longer need.
5107
+ var parts = EntityUtils.GatherEntity({
5108
+ entity: cEntity,
5109
+ });
5110
+ if (parts.length > 1) {
5111
+ // We'll cull all except the allowed number of siblings.
5112
+ cEntity._siblingGraphics = cEntity._siblingGraphics.slice(0, siblings);
5113
+ // We'll remove all that aren't in the allowed (direct) list.
5114
+ for (var i = 0; i < parts.length - 1; i++) {
5115
+ var part = parts[i];
5116
+ if (part && part instanceof Entity && params.viewer.entities.contains(part) && !cEntity._siblingGraphics.includes(part)) {
5117
+ params.viewer.entities.remove(part);
5118
+ }
5119
+ }
5120
+ if (cEntity._parentEntity) {
5121
+ console.warn("Point.Render: Parent entity was not null. This should not happen.");
5122
+ }
5123
+ }
5124
+ };
4712
5125
  if (!(type == Style.EPointType.Icon)) return [3 /*break*/, 9];
4713
5126
  iconUrlRows = style.iconUrl == null ? [] : style.iconUrl;
4714
5127
  iconUrlRows.forEach(function (row) {
@@ -4725,36 +5138,36 @@ var EntityRenderEngine;
4725
5138
  api = params.apiGetter.getApi(metadata.accountId);
4726
5139
  return [4 /*yield*/, api.Loading];
4727
5140
  case 1:
4728
- _c.sent();
5141
+ _e.sent();
4729
5142
  iconUrl = ClientFile.GetUrl({
4730
5143
  api: api,
4731
5144
  fileId: metadata.fileId,
4732
5145
  viaCdn: true
4733
5146
  });
4734
- _c.label = 2;
5147
+ _e.label = 2;
4735
5148
  case 2:
4736
5149
  if (!(!iconUrl && style.iconId)) return [3 /*break*/, 4];
4737
5150
  return [4 /*yield*/, params.api.Loading];
4738
5151
  case 3:
4739
- _c.sent();
5152
+ _e.sent();
4740
5153
  iconUrl = ClientFile.GetUrl({
4741
5154
  api: params.api,
4742
5155
  fileId: style.iconId,
4743
5156
  viaCdn: true
4744
5157
  });
4745
- _c.label = 4;
5158
+ _e.label = 4;
4746
5159
  case 4:
4747
5160
  image = null;
4748
5161
  if (!iconUrl) return [3 /*break*/, 8];
4749
- _c.label = 5;
5162
+ _e.label = 5;
4750
5163
  case 5:
4751
- _c.trys.push([5, 7, , 8]);
5164
+ _e.trys.push([5, 7, , 8]);
4752
5165
  return [4 /*yield*/, createImageBillboard(iconUrl)];
4753
5166
  case 6:
4754
- image = _c.sent();
5167
+ image = _e.sent();
4755
5168
  return [3 /*break*/, 8];
4756
5169
  case 7:
4757
- e_5 = _c.sent();
5170
+ e_5 = _e.sent();
4758
5171
  // Expanding the logging here so we can figure out why this is happening.
4759
5172
  // Most of the time the file is missing but we're getting some strange errors so I am including logging on the API settings as well.
4760
5173
  OneTimeError("ENTITY_RENDER_ENGINE_ICON_URL_ERROR_" + iconUrl, {
@@ -4773,34 +5186,64 @@ var EntityRenderEngine;
4773
5186
  disableDepthTest = Boolean(style.renderOnTop);
4774
5187
  if (iconScale > 0) {
4775
5188
  bColor = style.iconTintColor ? Calculator.GetColor(style.iconTintColor, entity, params.tags) : null;
4776
- cColor = bColor ? colorToCColor(bColor) : undefined;
5189
+ cColor_1 = bColor ? colorToCColor(bColor) : undefined;
4777
5190
  heightRef = getHeightRef(style);
4778
- cEntity = new Entity({
4779
- id: ObjectUtils.UId(10),
4780
- billboard: {
4781
- horizontalOrigin: HorizontalOrigin.CENTER,
4782
- verticalOrigin: VerticalOrigin.BOTTOM,
4783
- image: image.canvas,
4784
- heightReference: getHeightRef(style),
4785
- scale: iconScale,
4786
- disableDepthTestDistance: disableDepthTest ? Number.POSITIVE_INFINITY : undefined,
4787
- distanceDisplayCondition: getDisplayCondition(params.minDistance, params.maxDistance),
4788
- color: cColor
4789
- // Would be great once we have a setting for this.
4790
- // translucencyByDistance: getTranslucencyByDistance(params.minDistance, params.maxDistance),
4791
- },
4792
- position: EntityUtils.GetPos({
5191
+ if (!params.rendered || !params.rendered.billboard) {
5192
+ cEntity = new Entity({
5193
+ id: ObjectUtils.UId(10),
5194
+ billboard: {
5195
+ horizontalOrigin: HorizontalOrigin.CENTER,
5196
+ verticalOrigin: VerticalOrigin.BOTTOM,
5197
+ image: image.canvasDataUri,
5198
+ heightReference: getHeightRef(style),
5199
+ scale: iconScale,
5200
+ disableDepthTestDistance: disableDepthTest ? Number.POSITIVE_INFINITY : undefined,
5201
+ distanceDisplayCondition: getDisplayCondition(params.minDistance, params.maxDistance),
5202
+ color: new CallbackProperty(function () { return cColor_1; }, true),
5203
+ // Would be great once we have a setting for this.
5204
+ // translucencyByDistance: getTranslucencyByDistance(params.minDistance, params.maxDistance),
5205
+ },
5206
+ position: EntityUtils.GetPos({
5207
+ viewer: params.viewer,
5208
+ entity: entity,
5209
+ recordHeightRef: heightRef,
5210
+ returnHeightRef: heightRef
5211
+ }),
5212
+ show: true
5213
+ });
5214
+ }
5215
+ else {
5216
+ prepareExistingGraphic(params.rendered);
5217
+ cEntity = params.rendered;
5218
+ currentImgKey = cEntity.billboard._billboardImgKey;
5219
+ if (currentImgKey != iconUrl) {
5220
+ cEntity.billboard.image = new ConstantProperty(image.canvasDataUri);
5221
+ }
5222
+ cEntity.billboard.scale = new ConstantProperty(iconScale);
5223
+ cEntity.billboard.heightReference = new ConstantProperty(getHeightRef(style));
5224
+ cEntity.billboard.disableDepthTestDistance = new ConstantProperty(disableDepthTest ? Number.POSITIVE_INFINITY : undefined);
5225
+ cEntity.billboard.distanceDisplayCondition = new ConstantProperty(getDisplayCondition(params.minDistance, params.maxDistance));
5226
+ cEntity.position = new ConstantPositionProperty(EntityUtils.GetPos({
4793
5227
  viewer: params.viewer,
4794
5228
  entity: entity,
4795
5229
  recordHeightRef: heightRef,
4796
5230
  returnHeightRef: heightRef
4797
- }),
4798
- show: true
4799
- });
5231
+ }));
5232
+ // We'll use "SetDefaultColor" to updating the internal reference and to allow for an animation.
5233
+ CesiumEntityStyler.SetDefaultColor({
5234
+ color: cColor_1,
5235
+ entity: cEntity,
5236
+ viewer: params.viewer,
5237
+ override: true,
5238
+ requestRender: false
5239
+ });
5240
+ cEntity.show = true;
5241
+ }
4800
5242
  cEntity.billboard._billboardSize = image.height;
5243
+ cEntity.billboard._billboardImgKey = iconUrl;
4801
5244
  }
4802
5245
  }
4803
- _c.label = 9;
5246
+ _e.label = 9;
4804
5247
  case 9:
4805
5248
  if (type == Style.EPointType.Cylinder) {
4806
5249
  radius = EnsureNumber(Calculator.GetNumber(style.CylinderRadius, entity, params.tags));
@@ -4825,46 +5268,97 @@ var EntityRenderEngine;
4825
5268
  returnHeightRef: heightRef
4826
5269
  });
4827
5270
  extrusion = getCylinderExtrusion(entity, params.tags, heightRef, style.CylinderFillExtrusion);
4828
- cEntity = new Entity({
4829
- id: ObjectUtils.UId(10),
4830
- ellipse: {
4831
- semiMajorAxis: radius,
4832
- semiMinorAxis: radius,
4833
- material: cFill,
4834
- outlineWidth: null,
4835
- extrudedHeight: extrusion.value,
4836
- heightReference: heightRef,
4837
- extrudedHeightReference: extrusion.exHeightRef,
4838
- height: Cartographic.fromCartesian(pos3d).height,
4839
- zIndex: 1,
4840
- distanceDisplayCondition: getDisplayCondition(params.minDistance, params.maxDistance)
4841
- },
4842
- position: pos3d === null || pos3d === void 0 ? void 0 : pos3d.clone(),
4843
- show: true
4844
- });
4845
- if (outline && outlineWidth > 0) {
4846
- outlineExtrusion = getCylinderExtrusion(entity, params.tags, heightRef, style.CylinderBorderExtrusion);
4847
- // If this doesn't have its own extrusion, we must make it match the sibling.
4848
- // This way they render in a uniform way.
4849
- if (!outlineExtrusion.value && extrusion.value) {
4850
- outlineExtrusion.exHeightRef = extrusion.exHeightRef;
4851
- }
4852
- siblings.push(new Entity({
5271
+ hasOutline = outline && outlineWidth > 0;
5272
+ if (!params.rendered || !params.rendered.ellipse) {
5273
+ cEntity = new Entity({
4853
5274
  id: ObjectUtils.UId(10),
4854
5275
  ellipse: {
4855
- semiMajorAxis: radius + outlineWidth,
4856
- semiMinorAxis: radius + outlineWidth,
4857
- material: cOutline,
4858
- outlineWidth: undefined,
4859
- extrudedHeight: outlineExtrusion.value,
5276
+ semiMajorAxis: radius,
5277
+ semiMinorAxis: radius,
5278
+ material: cFill,
5279
+ outlineWidth: null,
5280
+ extrudedHeight: extrusion.value,
4860
5281
  heightReference: heightRef,
4861
- extrudedHeightReference: outlineExtrusion.exHeightRef,
5282
+ extrudedHeightReference: extrusion.exHeightRef,
4862
5283
  height: Cartographic.fromCartesian(pos3d).height,
4863
- zIndex: 2,
5284
+ zIndex: 1,
4864
5285
  distanceDisplayCondition: getDisplayCondition(params.minDistance, params.maxDistance)
4865
5286
  },
4866
- position: pos3d === null || pos3d === void 0 ? void 0 : pos3d.clone()
4867
- }));
5287
+ position: pos3d === null || pos3d === void 0 ? void 0 : pos3d.clone(),
5288
+ show: true
5289
+ });
5290
+ }
5291
+ else {
5292
+ prepareExistingGraphic(params.rendered, hasOutline ? 1 : 0);
5293
+ cEntity = params.rendered;
5294
+ cEntity.ellipse.semiMajorAxis = new ConstantProperty(radius);
5295
+ cEntity.ellipse.semiMinorAxis = new ConstantProperty(radius);
5296
+ cEntity.ellipse.outlineWidth = undefined;
5297
+ cEntity.ellipse.extrudedHeight = new ConstantProperty(extrusion.value);
5298
+ cEntity.ellipse.heightReference = new ConstantProperty(heightRef);
5299
+ cEntity.ellipse.extrudedHeightReference = new ConstantProperty(extrusion.exHeightRef);
5300
+ cEntity.ellipse.height = new ConstantProperty(Cartographic.fromCartesian(pos3d).height);
5301
+ cEntity.ellipse.zIndex = new ConstantProperty(1);
5302
+ cEntity.ellipse.distanceDisplayCondition = new ConstantProperty(getDisplayCondition(params.minDistance, params.maxDistance));
5303
+ cEntity.position = new ConstantPositionProperty(pos3d === null || pos3d === void 0 ? void 0 : pos3d.clone());
5304
+ // We'll use "SetDefaultColor" to updating the internal reference and to allow for an animation.
5305
+ // WARNING: ellipse does not support animation (yet?).
5306
+ CesiumEntityStyler.SetDefaultColor({
5307
+ color: cFill,
5308
+ entity: cEntity,
5309
+ viewer: params.viewer,
5310
+ override: true,
5311
+ requestRender: false
5312
+ });
5313
+ cEntity.show = true;
5314
+ }
5315
+ if (hasOutline) {
5316
+ outlineExtrusion = getCylinderExtrusion(entity, params.tags, heightRef, style.CylinderBorderExtrusion);
5317
+ // If this doesn't have its own extrusion, we must make it match the sibling.
5318
+ // This way they render in a uniform way.
5319
+ if (!outlineExtrusion.value && extrusion.value) {
5320
+ outlineExtrusion.exHeightRef = extrusion.exHeightRef;
5321
+ }
5322
+ outlineEntity = (_d = (_c = params.rendered) === null || _c === void 0 ? void 0 : _c._siblingGraphics) === null || _d === void 0 ? void 0 : _d[0];
5323
+ if (outlineEntity && outlineEntity.ellipse) {
5324
+ outlineEntity.ellipse.semiMajorAxis = new ConstantProperty(radius + outlineWidth);
5325
+ outlineEntity.ellipse.semiMinorAxis = new ConstantProperty(radius + outlineWidth);
5326
+ outlineEntity.ellipse.extrudedHeight = new ConstantProperty(outlineExtrusion.value);
5327
+ outlineEntity.ellipse.heightReference = new ConstantProperty(heightRef);
5328
+ outlineEntity.ellipse.extrudedHeightReference = new ConstantProperty(outlineExtrusion.exHeightRef);
5329
+ outlineEntity.ellipse.height = new ConstantProperty(Cartographic.fromCartesian(pos3d).height);
5330
+ outlineEntity.ellipse.zIndex = new ConstantProperty(2);
5331
+ outlineEntity.ellipse.distanceDisplayCondition = new ConstantProperty(getDisplayCondition(params.minDistance, params.maxDistance));
5332
+ // We'll use "SetDefaultColor" to updating the internal reference and to allow for an animation.
5333
+ // WARNING: ellipse does not support animation (yet?).
5334
+ CesiumEntityStyler.SetDefaultColor({
5335
+ color: cOutline,
5336
+ entity: outlineEntity,
5337
+ viewer: params.viewer,
5338
+ override: true,
5339
+ requestRender: false
5340
+ });
5341
+ outlineEntity.show = true;
5342
+ }
5343
+ else {
5344
+ outlineEntity = new Entity({
5345
+ id: ObjectUtils.UId(10),
5346
+ ellipse: {
5347
+ semiMajorAxis: radius + outlineWidth,
5348
+ semiMinorAxis: radius + outlineWidth,
5349
+ material: cOutline,
5350
+ outlineWidth: undefined,
5351
+ extrudedHeight: outlineExtrusion.value,
5352
+ heightReference: heightRef,
5353
+ extrudedHeightReference: outlineExtrusion.exHeightRef,
5354
+ height: Cartographic.fromCartesian(pos3d).height,
5355
+ zIndex: 2,
5356
+ distanceDisplayCondition: getDisplayCondition(params.minDistance, params.maxDistance)
5357
+ },
5358
+ position: pos3d === null || pos3d === void 0 ? void 0 : pos3d.clone()
5359
+ });
5360
+ }
5361
+ siblings.push(outlineEntity);
4868
5362
  }
4869
5363
  }
4870
5364
  if (!cEntity) {
@@ -4881,33 +5375,66 @@ var EntityRenderEngine;
4881
5375
  heightRef = getHeightRef(style);
4882
5376
  circleBillboard = createCircleBillboard(size, cColor.toCssColorString());
4883
5377
  disableDepthTest = Boolean(style.renderOnTop);
4884
- cEntity = new Entity({
4885
- id: ObjectUtils.UId(10),
4886
- // point: {
4887
- // pixelSize: size,
4888
- // color: cColor,
4889
- // heightReference: getHeightRef(style),
4890
- // distanceDisplayCondition: getDisplayCondition(params.minDistance, params.maxDistance)
4891
- // },
4892
- // We are generating a billboard instead of using the point.
4893
- // This is because points were behaving strangely where they would appear oblong shapes.
4894
- // This occurred consistently when rendering many icons and points at the same time.
4895
- billboard: {
4896
- height: circleBillboard.height,
4897
- width: circleBillboard.width,
4898
- image: circleBillboard.canvas,
4899
- heightReference: heightRef,
4900
- distanceDisplayCondition: getDisplayCondition(params.minDistance, params.maxDistance),
4901
- disableDepthTestDistance: disableDepthTest ? Number.POSITIVE_INFINITY : undefined
4902
- },
4903
- position: EntityUtils.GetPos({
5378
+ if (!params.rendered || !params.rendered.billboard) {
5379
+ cEntity = new Entity({
5380
+ id: ObjectUtils.UId(10),
5381
+ // point: {
5382
+ // pixelSize: size,
5383
+ // color: cColor,
5384
+ // heightReference: getHeightRef(style),
5385
+ // distanceDisplayCondition: getDisplayCondition(params.minDistance, params.maxDistance)
5386
+ // },
5387
+ // We are generating a billboard instead of using the point.
5388
+ // This is because points were behaving strangely where they would appear oblong shapes.
5389
+ // This occurred consistently when rendering many icons and points at the same time.
5390
+ billboard: {
5391
+ height: circleBillboard.height,
5392
+ width: circleBillboard.width,
5393
+ image: circleBillboard.canvasDataUri,
5394
+ color: new CallbackProperty(function () { return undefined; }, true),
5395
+ heightReference: heightRef,
5396
+ distanceDisplayCondition: getDisplayCondition(params.minDistance, params.maxDistance),
5397
+ disableDepthTestDistance: disableDepthTest ? Number.POSITIVE_INFINITY : undefined
5398
+ },
5399
+ position: EntityUtils.GetPos({
5400
+ viewer: params.viewer,
5401
+ entity: entity,
5402
+ recordHeightRef: heightRef,
5403
+ returnHeightRef: heightRef
5404
+ }),
5405
+ show: true
5406
+ });
5407
+ }
5408
+ else {
5409
+ prepareExistingGraphic(params.rendered);
5410
+ cEntity = params.rendered;
5411
+ imgKey = "".concat(size, "-").concat(cColor.toCssColorString());
5412
+ currentImgKey = cEntity.billboard._billboardImgKey;
5413
+ if (currentImgKey != imgKey) {
5414
+ cEntity.billboard.image = new ConstantProperty(circleBillboard.canvasDataUri);
5415
+ }
5416
+ cEntity.billboard.height = new ConstantProperty(circleBillboard.height);
5417
+ cEntity.billboard.width = new ConstantProperty(circleBillboard.width);
5418
+ cEntity.billboard.heightReference = new ConstantProperty(heightRef);
5419
+ cEntity.billboard.distanceDisplayCondition = new ConstantProperty(getDisplayCondition(params.minDistance, params.maxDistance));
5420
+ cEntity.billboard.disableDepthTestDistance = new ConstantProperty(disableDepthTest ? Number.POSITIVE_INFINITY : undefined);
5421
+ cEntity.position = new ConstantPositionProperty(EntityUtils.GetPos({
4904
5422
  viewer: params.viewer,
4905
5423
  entity: entity,
4906
5424
  recordHeightRef: heightRef,
4907
5425
  returnHeightRef: heightRef
4908
- }),
4909
- show: true
4910
- });
5426
+ }));
5427
+ // We'll use "SetDefaultColor" to updating the internal reference and to allow for an animation.
5428
+ CesiumEntityStyler.SetDefaultColor({
5429
+ color: cColor,
5430
+ entity: cEntity,
5431
+ viewer: params.viewer,
5432
+ override: true,
5433
+ requestRender: false
5434
+ });
5435
+ cEntity.show = true;
5436
+ cEntity.billboard._billboardImgKey = imgKey;
5437
+ }
4911
5438
  cEntity.billboard._billboardSize = Math.ceil(circleBillboard.height / 2);
4912
5439
  }
4913
5440
  if (cEntity) {
@@ -4920,16 +5447,16 @@ var EntityRenderEngine;
4920
5447
  }
4921
5448
  Point.Render = Render;
4922
5449
  function RenderGroup(params) {
4923
- var _a, _b, _c;
5450
+ var _a, _b, _c, _d;
4924
5451
  return __awaiter(this, void 0, void 0, function () {
4925
- var api, cEntities, i, entity, zoomItem, style, _d, tagIds, tags, pStyle, cEntity, name_2;
4926
- return __generator(this, function (_e) {
4927
- switch (_e.label) {
5452
+ var api, cEntities, i, entity, zoomItem, style, _e, tagIds, tags, pStyle, cEntity, name_2;
5453
+ return __generator(this, function (_f) {
5454
+ switch (_f.label) {
4928
5455
  case 0:
4929
5456
  api = params.apiGetter.getApi();
4930
5457
  cEntities = {};
4931
5458
  i = 0;
4932
- _e.label = 1;
5459
+ _f.label = 1;
4933
5460
  case 1:
4934
5461
  if (!(i < params.entities.length)) return [3 /*break*/, 11];
4935
5462
  entity = params.entities[i];
@@ -4937,13 +5464,13 @@ var EntityRenderEngine;
4937
5464
  if (!(zoomItem.StyleID != -1)) return [3 /*break*/, 3];
4938
5465
  return [4 /*yield*/, getStyle(api, entity, zoomItem.StyleID)];
4939
5466
  case 2:
4940
- _d = (_a = (_e.sent())) === null || _a === void 0 ? void 0 : _a.Settings;
5467
+ _e = (_a = (_f.sent())) === null || _a === void 0 ? void 0 : _a.Settings;
4941
5468
  return [3 /*break*/, 4];
4942
5469
  case 3:
4943
- _d = zoomItem.Style;
4944
- _e.label = 4;
5470
+ _e = zoomItem.Style;
5471
+ _f.label = 4;
4945
5472
  case 4:
4946
- style = _d;
5473
+ style = _e;
4947
5474
  tagIds = entity.Bruce["Layer.ID"];
4948
5475
  tags = [];
4949
5476
  if (!(tagIds && tagIds.length > 0)) return [3 /*break*/, 6];
@@ -4952,8 +5479,8 @@ var EntityRenderEngine;
4952
5479
  tagIds: tagIds
4953
5480
  })];
4954
5481
  case 5:
4955
- tags = (_e.sent()).tags;
4956
- _e.label = 6;
5482
+ tags = (_f.sent()).tags;
5483
+ _f.label = 6;
4957
5484
  case 6:
4958
5485
  pStyle = (_b = style === null || style === void 0 ? void 0 : style.pointStyle) !== null && _b !== void 0 ? _b : {};
4959
5486
  return [4 /*yield*/, Render({
@@ -4964,20 +5491,21 @@ var EntityRenderEngine;
4964
5491
  api: api,
4965
5492
  apiGetter: params.apiGetter,
4966
5493
  maxDistance: zoomItem.MaxZoom,
4967
- minDistance: zoomItem.MinZoom
5494
+ minDistance: zoomItem.MinZoom,
5495
+ rendered: (_c = params.rendered) === null || _c === void 0 ? void 0 : _c[entity.Bruce.ID]
4968
5496
  })];
4969
5497
  case 7:
4970
- cEntity = _e.sent();
5498
+ cEntity = _f.sent();
4971
5499
  if (!cEntity) return [3 /*break*/, 9];
4972
5500
  return [4 /*yield*/, getName(api, entity)];
4973
5501
  case 8:
4974
- name_2 = _e.sent();
5502
+ name_2 = _f.sent();
4975
5503
  cEntity.name = name_2;
4976
- cEntity._renderGroup = getRenderGroupId(zoomItem, (_c = params.viewer) === null || _c === void 0 ? void 0 : _c.terrainProvider);
4977
- _e.label = 9;
5504
+ cEntity._renderGroup = getRenderGroupId(zoomItem, (_d = params.viewer) === null || _d === void 0 ? void 0 : _d.terrainProvider);
5505
+ _f.label = 9;
4978
5506
  case 9:
4979
5507
  cEntities[entity.Bruce.ID] = cEntity;
4980
- _e.label = 10;
5508
+ _f.label = 10;
4981
5509
  case 10:
4982
5510
  i++;
4983
5511
  return [3 /*break*/, 1];
@@ -5062,52 +5590,110 @@ var EntityRenderEngine;
5062
5590
  if (style.drapeOver == "ALL") {
5063
5591
  classification = ClassificationType.BOTH;
5064
5592
  }
5065
- var cEntity = new Entity({
5066
- id: ObjectUtils.UId(10),
5067
- polyline: units == "px" ? {
5068
- positions: posses,
5069
- material: cColor,
5070
- width: width,
5071
- classificationType: classification,
5072
- arcType: ArcType.GEODESIC,
5073
- zIndex: getZIndex(style, entity, params.tags),
5074
- clampToGround: heightRef == HeightReference.CLAMP_TO_GROUND,
5075
- distanceDisplayCondition: getDisplayCondition(params.minDistance, params.maxDistance)
5076
- } : null,
5077
- corridor: units == "m" ? {
5078
- positions: posses,
5079
- material: cColor,
5080
- width: width,
5081
- classificationType: classification,
5082
- heightReference: heightRef,
5083
- zIndex: getZIndex(style, entity, params.tags),
5084
- distanceDisplayCondition: getDisplayCondition(params.minDistance, params.maxDistance, width),
5085
- cornerType: CornerType.MITERED,
5086
- shadows: ShadowMode.ENABLED,
5087
- fill: true
5088
- } : null,
5089
- position: EntityUtils.GetPos({
5593
+ var cEntity = null;
5594
+ if (!params.rendered || ((!params.rendered.polyline && units == "px") ||
5595
+ (!params.rendered.corridor && units == "m"))) {
5596
+ cEntity = new Entity({
5597
+ id: ObjectUtils.UId(10),
5598
+ polyline: units == "px" ? {
5599
+ positions: posses,
5600
+ material: cColor,
5601
+ width: width,
5602
+ classificationType: classification,
5603
+ arcType: ArcType.GEODESIC,
5604
+ zIndex: getZIndex(style, entity, params.tags),
5605
+ clampToGround: heightRef == HeightReference.CLAMP_TO_GROUND,
5606
+ distanceDisplayCondition: getDisplayCondition(params.minDistance, params.maxDistance)
5607
+ } : null,
5608
+ corridor: units == "m" ? {
5609
+ positions: posses,
5610
+ material: cColor,
5611
+ width: width,
5612
+ classificationType: classification,
5613
+ heightReference: heightRef,
5614
+ zIndex: getZIndex(style, entity, params.tags),
5615
+ distanceDisplayCondition: getDisplayCondition(params.minDistance, params.maxDistance, width),
5616
+ cornerType: CornerType.MITERED,
5617
+ shadows: ShadowMode.ENABLED,
5618
+ fill: true
5619
+ } : null,
5620
+ position: EntityUtils.GetPos({
5621
+ viewer: params.viewer,
5622
+ entity: entity,
5623
+ recordHeightRef: heightRef,
5624
+ returnHeightRef: heightRef
5625
+ }),
5626
+ show: true
5627
+ });
5628
+ }
5629
+ else {
5630
+ // Gather entity in case previous version had sibling graphics we no longer need.
5631
+ var parts = EntityUtils.GatherEntity({
5632
+ entity: cEntity,
5633
+ });
5634
+ if (parts.length > 1) {
5635
+ // Kill all expect last part. Last one is the primary entity.
5636
+ for (var i = 0; i < parts.length - 1; i++) {
5637
+ var part = parts[i];
5638
+ if (part && part instanceof Entity && params.viewer.entities.contains(part)) {
5639
+ params.viewer.entities.remove(part);
5640
+ }
5641
+ }
5642
+ cEntity._siblingGraphics = [];
5643
+ if (cEntity._parentEntity) {
5644
+ console.warn("Polyline.Render: Parent entity was not null. This should not happen.");
5645
+ }
5646
+ }
5647
+ cEntity = params.rendered;
5648
+ if (units == "px") {
5649
+ cEntity.polyline.positions = new ConstantProperty(posses);
5650
+ cEntity.polyline.width = new ConstantProperty(width);
5651
+ cEntity.polyline.classificationType = new ConstantProperty(classification);
5652
+ cEntity.polyline.zIndex = new ConstantProperty(getZIndex(style, entity, params.tags));
5653
+ cEntity.polyline.clampToGround = new ConstantProperty(heightRef == HeightReference.CLAMP_TO_GROUND);
5654
+ cEntity.polyline.distanceDisplayCondition = new ConstantProperty(getDisplayCondition(params.minDistance, params.maxDistance));
5655
+ cEntity.corridor = undefined;
5656
+ }
5657
+ else {
5658
+ cEntity.corridor.positions = new ConstantProperty(posses);
5659
+ cEntity.corridor.width = new ConstantProperty(width);
5660
+ cEntity.corridor.classificationType = new ConstantProperty(classification);
5661
+ cEntity.corridor.heightReference = new ConstantProperty(heightRef);
5662
+ cEntity.corridor.zIndex = new ConstantProperty(getZIndex(style, entity, params.tags));
5663
+ cEntity.corridor.distanceDisplayCondition = new ConstantProperty(getDisplayCondition(params.minDistance, params.maxDistance, width));
5664
+ cEntity.polyline = undefined;
5665
+ }
5666
+ // We'll use "SetDefaultColor" to updating the internal reference and to allow for an animation.
5667
+ // WARNING: polyline does not support animation (yet?).
5668
+ CesiumEntityStyler.SetDefaultColor({
5669
+ color: cColor,
5670
+ entity: cEntity,
5671
+ viewer: params.viewer,
5672
+ override: true,
5673
+ requestRender: false
5674
+ });
5675
+ cEntity.position = new ConstantPositionProperty(EntityUtils.GetPos({
5090
5676
  viewer: params.viewer,
5091
5677
  entity: entity,
5092
5678
  recordHeightRef: heightRef,
5093
5679
  returnHeightRef: heightRef
5094
- }),
5095
- show: true
5096
- });
5680
+ }));
5681
+ cEntity.show = true;
5682
+ }
5097
5683
  return cEntity;
5098
5684
  }
5099
5685
  Polyline.Render = Render;
5100
5686
  function RenderGroup(params) {
5101
- var _a, _b, _c;
5687
+ var _a, _b, _c, _d;
5102
5688
  return __awaiter(this, void 0, void 0, function () {
5103
- var api, cEntities, i, entity, zoomItem, style, _d, tagIds, tags, lStyle, cEntity, name_3;
5104
- return __generator(this, function (_e) {
5105
- switch (_e.label) {
5689
+ var api, cEntities, i, entity, zoomItem, style, _e, tagIds, tags, lStyle, cEntity, name_3;
5690
+ return __generator(this, function (_f) {
5691
+ switch (_f.label) {
5106
5692
  case 0:
5107
5693
  api = params.apiGetter.getApi();
5108
5694
  cEntities = {};
5109
5695
  i = 0;
5110
- _e.label = 1;
5696
+ _f.label = 1;
5111
5697
  case 1:
5112
5698
  if (!(i < params.entities.length)) return [3 /*break*/, 9];
5113
5699
  entity = params.entities[i];
@@ -5115,13 +5701,13 @@ var EntityRenderEngine;
5115
5701
  if (!(zoomItem.StyleID != -1)) return [3 /*break*/, 3];
5116
5702
  return [4 /*yield*/, getStyle(api, entity, zoomItem.StyleID)];
5117
5703
  case 2:
5118
- _d = (_a = (_e.sent())) === null || _a === void 0 ? void 0 : _a.Settings;
5704
+ _e = (_a = (_f.sent())) === null || _a === void 0 ? void 0 : _a.Settings;
5119
5705
  return [3 /*break*/, 4];
5120
5706
  case 3:
5121
- _d = zoomItem.Style;
5122
- _e.label = 4;
5707
+ _e = zoomItem.Style;
5708
+ _f.label = 4;
5123
5709
  case 4:
5124
- style = _d;
5710
+ style = _e;
5125
5711
  tagIds = entity.Bruce["Layer.ID"];
5126
5712
  tags = [];
5127
5713
  if (!(tagIds && tagIds.length > 0)) return [3 /*break*/, 6];
@@ -5130,8 +5716,8 @@ var EntityRenderEngine;
5130
5716
  tagIds: tagIds
5131
5717
  })];
5132
5718
  case 5:
5133
- tags = (_e.sent()).tags;
5134
- _e.label = 6;
5719
+ tags = (_f.sent()).tags;
5720
+ _f.label = 6;
5135
5721
  case 6:
5136
5722
  lStyle = (_b = style === null || style === void 0 ? void 0 : style.polylineStyle) !== null && _b !== void 0 ? _b : {};
5137
5723
  cEntity = Render({
@@ -5140,16 +5726,17 @@ var EntityRenderEngine;
5140
5726
  tags: tags,
5141
5727
  viewer: params.viewer,
5142
5728
  maxDistance: zoomItem.MaxZoom,
5143
- minDistance: zoomItem.MinZoom
5729
+ minDistance: zoomItem.MinZoom,
5730
+ rendered: (_c = params.rendered) === null || _c === void 0 ? void 0 : _c[entity.Bruce.ID]
5144
5731
  });
5145
5732
  if (!cEntity) return [3 /*break*/, 8];
5146
5733
  return [4 /*yield*/, getName(api, entity)];
5147
5734
  case 7:
5148
- name_3 = _e.sent();
5735
+ name_3 = _f.sent();
5149
5736
  cEntity.name = name_3;
5150
- cEntity._renderGroup = getRenderGroupId(zoomItem, (_c = params.viewer) === null || _c === void 0 ? void 0 : _c.terrainProvider);
5737
+ cEntity._renderGroup = getRenderGroupId(zoomItem, (_d = params.viewer) === null || _d === void 0 ? void 0 : _d.terrainProvider);
5151
5738
  cEntities[entity.Bruce.ID] = cEntity;
5152
- _e.label = 8;
5739
+ _f.label = 8;
5153
5740
  case 8:
5154
5741
  i++;
5155
5742
  return [3 /*break*/, 1];
@@ -5163,7 +5750,7 @@ var EntityRenderEngine;
5163
5750
  var Polygon;
5164
5751
  (function (Polygon) {
5165
5752
  function Render(params) {
5166
- var _a, _b;
5753
+ var _a, _b, _c, _d;
5167
5754
  var entity = params.entity;
5168
5755
  var pRings = (_a = entity.geometry) === null || _a === void 0 ? void 0 : _a.Polygon;
5169
5756
  if (pRings == null || pRings.length <= 0) {
@@ -5220,30 +5807,85 @@ var EntityRenderEngine;
5220
5807
  if (style.drapeOver == "ALL") {
5221
5808
  classification = ClassificationType.BOTH;
5222
5809
  }
5223
- var cEntity = new Entity({
5224
- id: ObjectUtils.UId(10),
5225
- polygon: {
5226
- hierarchy: new PolygonHierarchy(posses, holePosses.map(function (x) { return new PolygonHierarchy(x); })),
5227
- material: cFillColor,
5228
- extrudedHeight: extrusion.value,
5229
- extrudedHeightReference: extrusion.exHeightRef,
5230
- shadows: ShadowMode.ENABLED,
5231
- heightReference: heightRef,
5232
- classificationType: classification,
5233
- perPositionHeight: heightRef == HeightReference.CLAMP_TO_GROUND ? false : true,
5234
- zIndex: zIndex,
5235
- distanceDisplayCondition: getDisplayCondition(params.minDistance, params.maxDistance, width <= 0 || !cLineColor || units == "m" ? size : null, true)
5236
- },
5237
- position: EntityUtils.GetPos({
5810
+ var prepareExistingGraphic = function (cEntity, siblings) {
5811
+ if (siblings === void 0) { siblings = 0; }
5812
+ // Gather entity in case previous version had sibling graphics we no longer need.
5813
+ var parts = EntityUtils.GatherEntity({
5814
+ entity: cEntity,
5815
+ });
5816
+ if (parts.length > 1) {
5817
+ // We'll cull all except the allowed number of siblings.
5818
+ cEntity._siblingGraphics = cEntity._siblingGraphics.slice(0, siblings);
5819
+ // We'll remove all that aren't in the allowed (direct) list.
5820
+ for (var i = 0; i < parts.length - 1; i++) {
5821
+ var part = parts[i];
5822
+ if (part && part instanceof Entity && params.viewer.entities.contains(part) && !cEntity._siblingGraphics.includes(part)) {
5823
+ params.viewer.entities.remove(part);
5824
+ }
5825
+ }
5826
+ if (cEntity._parentEntity) {
5827
+ console.warn("Point.Render: Parent entity was not null. This should not happen.");
5828
+ }
5829
+ }
5830
+ };
5831
+ var hasOutline = width > 0 && cLineColor;
5832
+ var cEntity = null;
5833
+ if (!params.rendered || !params.rendered.polygon) {
5834
+ cEntity = new Entity({
5835
+ id: ObjectUtils.UId(10),
5836
+ polygon: {
5837
+ hierarchy: new PolygonHierarchy(posses, holePosses.map(function (x) { return new PolygonHierarchy(x); })),
5838
+ material: cFillColor,
5839
+ extrudedHeight: extrusion.value,
5840
+ extrudedHeightReference: extrusion.exHeightRef,
5841
+ shadows: ShadowMode.ENABLED,
5842
+ heightReference: heightRef,
5843
+ classificationType: classification,
5844
+ perPositionHeight: heightRef == HeightReference.CLAMP_TO_GROUND ? false : true,
5845
+ zIndex: zIndex,
5846
+ distanceDisplayCondition: getDisplayCondition(params.minDistance, params.maxDistance, width <= 0 || !cLineColor || units == "m" ? size : null, true)
5847
+ },
5848
+ position: EntityUtils.GetPos({
5849
+ viewer: params.viewer,
5850
+ entity: entity,
5851
+ recordHeightRef: heightRef,
5852
+ returnHeightRef: heightRef
5853
+ }),
5854
+ show: true
5855
+ });
5856
+ }
5857
+ else {
5858
+ // Polygons can have more siblings for the related hole graphics.
5859
+ // So this is a "good enough" way rather than perfect as it only preserves the outline.
5860
+ prepareExistingGraphic(params.rendered, hasOutline ? 1 : 0);
5861
+ cEntity = params.rendered;
5862
+ cEntity.polygon.hierarchy = new ConstantProperty(new PolygonHierarchy(posses, holePosses.map(function (x) { return new PolygonHierarchy(x); })));
5863
+ cEntity.polygon.extrudedHeight = new ConstantProperty(extrusion.value);
5864
+ cEntity.polygon.extrudedHeightReference = new ConstantProperty(extrusion.exHeightRef);
5865
+ cEntity.polygon.shadows = new ConstantProperty(ShadowMode.ENABLED);
5866
+ cEntity.polygon.heightReference = new ConstantProperty(heightRef);
5867
+ cEntity.polygon.classificationType = new ConstantProperty(classification);
5868
+ cEntity.polygon.perPositionHeight = new ConstantProperty(heightRef == HeightReference.CLAMP_TO_GROUND ? false : true);
5869
+ cEntity.polygon.zIndex = new ConstantProperty(zIndex);
5870
+ cEntity.polygon.distanceDisplayCondition = new ConstantProperty(getDisplayCondition(params.minDistance, params.maxDistance, width <= 0 || !cLineColor || units == "m" ? size : null, true));
5871
+ cEntity.position = new ConstantPositionProperty(EntityUtils.GetPos({
5238
5872
  viewer: params.viewer,
5239
5873
  entity: entity,
5240
5874
  recordHeightRef: heightRef,
5241
5875
  returnHeightRef: heightRef
5242
- }),
5243
- show: true
5244
- });
5245
- cEntity._siblingGraphics = [];
5246
- if (width > 0 && cLineColor) {
5876
+ }));
5877
+ // We'll use "SetDefaultColor" to updating the internal reference and to allow for an animation.
5878
+ // WARNING: polygon does not support animation (yet?).
5879
+ CesiumEntityStyler.SetDefaultColor({
5880
+ color: cFillColor,
5881
+ entity: cEntity,
5882
+ viewer: params.viewer,
5883
+ override: true,
5884
+ requestRender: false
5885
+ });
5886
+ cEntity.show = true;
5887
+ }
5888
+ if (hasOutline) {
5247
5889
  var borderHeight = undefined;
5248
5890
  if (heightRef != HeightReference.CLAMP_TO_GROUND) {
5249
5891
  if (flattenPoints) {
@@ -5267,33 +5909,62 @@ var EntityRenderEngine;
5267
5909
  else {
5268
5910
  borderPosses = posses.map(function (x) { return x.clone ? x.clone() : __assign({}, x); });
5269
5911
  }
5270
- var cEntityBorder = new Entity({
5271
- id: ObjectUtils.UId(10),
5272
- polyline: units == "px" ? new PolylineGraphics({
5273
- positions: borderPosses,
5274
- material: cLineColor,
5275
- width: width,
5276
- clampToGround: heightRef == HeightReference.CLAMP_TO_GROUND,
5277
- classificationType: ClassificationType.TERRAIN,
5278
- arcType: ArcType.GEODESIC,
5279
- zIndex: zIndex,
5280
- distanceDisplayCondition: getDisplayCondition(params.minDistance, params.maxDistance)
5281
- }) : null,
5282
- corridor: units == "m" ? {
5283
- positions: borderPosses,
5284
- material: cLineColor,
5285
- heightReference: heightRef,
5286
- height: borderHeight,
5287
- width: width,
5288
- fill: true,
5289
- zIndex: zIndex + 1,
5290
- cornerType: CornerType.MITERED,
5291
- classificationType: classification,
5292
- distanceDisplayCondition: getDisplayCondition(params.minDistance, params.maxDistance, width),
5293
- shadows: ShadowMode.ENABLED
5294
- } : null,
5295
- show: true
5296
- });
5912
+ var cEntityBorder = (_d = (_c = params.rendered) === null || _c === void 0 ? void 0 : _c._siblingGraphics) === null || _d === void 0 ? void 0 : _d[0];
5913
+ cEntity._siblingGraphics = [];
5914
+ if (!cEntityBorder || ((!cEntityBorder.polyline && units == "px") ||
5915
+ (!cEntityBorder.corridor && units == "m"))) {
5916
+ cEntityBorder = new Entity({
5917
+ id: ObjectUtils.UId(10),
5918
+ polyline: units == "px" ? new PolylineGraphics({
5919
+ positions: borderPosses,
5920
+ material: cLineColor,
5921
+ width: width,
5922
+ clampToGround: heightRef == HeightReference.CLAMP_TO_GROUND,
5923
+ classificationType: ClassificationType.TERRAIN,
5924
+ arcType: ArcType.GEODESIC,
5925
+ zIndex: zIndex,
5926
+ distanceDisplayCondition: getDisplayCondition(params.minDistance, params.maxDistance)
5927
+ }) : null,
5928
+ corridor: units == "m" ? {
5929
+ positions: borderPosses,
5930
+ material: cLineColor,
5931
+ heightReference: heightRef,
5932
+ height: borderHeight,
5933
+ width: width,
5934
+ fill: true,
5935
+ zIndex: zIndex + 1,
5936
+ cornerType: CornerType.MITERED,
5937
+ classificationType: classification,
5938
+ distanceDisplayCondition: getDisplayCondition(params.minDistance, params.maxDistance, width),
5939
+ shadows: ShadowMode.ENABLED
5940
+ } : null,
5941
+ show: true
5942
+ });
5943
+ }
5944
+ else {
5945
+ if (units == "px") {
5946
+ cEntityBorder.polyline.positions = new ConstantProperty(borderPosses);
5947
+ cEntityBorder.polyline.width = new ConstantProperty(width);
5948
+ cEntityBorder.polyline.clampToGround = new ConstantProperty(heightRef == HeightReference.CLAMP_TO_GROUND);
5949
+ cEntityBorder.polyline.classificationType = new ConstantProperty(ClassificationType.TERRAIN);
5950
+ cEntityBorder.polyline.zIndex = new ConstantProperty(zIndex);
5951
+ cEntityBorder.polyline.distanceDisplayCondition = new ConstantProperty(getDisplayCondition(params.minDistance, params.maxDistance));
5952
+ cEntityBorder.polyline.material = new ColorMaterialProperty(cLineColor);
5953
+ cEntityBorder.corridor = undefined;
5954
+ }
5955
+ else {
5956
+ cEntityBorder.corridor.positions = new ConstantProperty(borderPosses);
5957
+ cEntityBorder.corridor.heightReference = new ConstantProperty(heightRef);
5958
+ cEntityBorder.corridor.height = new ConstantProperty(borderHeight);
5959
+ cEntityBorder.corridor.width = new ConstantProperty(width);
5960
+ cEntityBorder.corridor.fill = new ConstantProperty(true);
5961
+ cEntityBorder.corridor.zIndex = new ConstantProperty(zIndex + 1);
5962
+ cEntityBorder.corridor.distanceDisplayCondition = new ConstantProperty(getDisplayCondition(params.minDistance, params.maxDistance, width));
5963
+ cEntityBorder.corridor.material = new ColorMaterialProperty(cLineColor);
5964
+ cEntityBorder.polyline = undefined;
5965
+ }
5966
+ cEntityBorder.show = true;
5967
+ }
5297
5968
  cEntityBorder._parentEntity = cEntity;
5298
5969
  cEntity._siblingGraphics.push(cEntityBorder);
5299
5970
  for (var i = 0; i < holePosses.length; i++) {
@@ -5330,20 +6001,23 @@ var EntityRenderEngine;
5330
6001
  cEntityHole._parentEntity = cEntity;
5331
6002
  }
5332
6003
  }
6004
+ else {
6005
+ cEntity._siblingGraphics = [];
6006
+ }
5333
6007
  return cEntity;
5334
6008
  }
5335
6009
  Polygon.Render = Render;
5336
6010
  function RenderGroup(params) {
5337
- var _a, _b, _c;
6011
+ var _a, _b, _c, _d;
5338
6012
  return __awaiter(this, void 0, void 0, function () {
5339
- var api, cEntities, i, entity, zoomItem, style, _d, tagIds, tags, pStyle, cEntity, name_4;
5340
- return __generator(this, function (_e) {
5341
- switch (_e.label) {
6013
+ var api, cEntities, i, entity, zoomItem, style, _e, tagIds, tags, pStyle, cEntity, name_4;
6014
+ return __generator(this, function (_f) {
6015
+ switch (_f.label) {
5342
6016
  case 0:
5343
6017
  api = params.apiGetter.getApi();
5344
6018
  cEntities = {};
5345
6019
  i = 0;
5346
- _e.label = 1;
6020
+ _f.label = 1;
5347
6021
  case 1:
5348
6022
  if (!(i < params.entities.length)) return [3 /*break*/, 9];
5349
6023
  entity = params.entities[i];
@@ -5351,13 +6025,13 @@ var EntityRenderEngine;
5351
6025
  if (!(zoomItem.StyleID != -1)) return [3 /*break*/, 3];
5352
6026
  return [4 /*yield*/, getStyle(api, entity, zoomItem.StyleID)];
5353
6027
  case 2:
5354
- _d = (_a = (_e.sent())) === null || _a === void 0 ? void 0 : _a.Settings;
6028
+ _e = (_a = (_f.sent())) === null || _a === void 0 ? void 0 : _a.Settings;
5355
6029
  return [3 /*break*/, 4];
5356
6030
  case 3:
5357
- _d = zoomItem.Style;
5358
- _e.label = 4;
6031
+ _e = zoomItem.Style;
6032
+ _f.label = 4;
5359
6033
  case 4:
5360
- style = _d;
6034
+ style = _e;
5361
6035
  tagIds = entity.Bruce["Layer.ID"];
5362
6036
  tags = [];
5363
6037
  if (!(tagIds && tagIds.length > 0)) return [3 /*break*/, 6];
@@ -5366,8 +6040,8 @@ var EntityRenderEngine;
5366
6040
  tagIds: tagIds
5367
6041
  })];
5368
6042
  case 5:
5369
- tags = (_e.sent()).tags;
5370
- _e.label = 6;
6043
+ tags = (_f.sent()).tags;
6044
+ _f.label = 6;
5371
6045
  case 6:
5372
6046
  pStyle = (_b = style === null || style === void 0 ? void 0 : style.polygonStyle) !== null && _b !== void 0 ? _b : {};
5373
6047
  cEntity = Render({
@@ -5376,16 +6050,17 @@ var EntityRenderEngine;
5376
6050
  tags: tags,
5377
6051
  viewer: params.viewer,
5378
6052
  maxDistance: zoomItem.MaxZoom,
5379
- minDistance: zoomItem.MinZoom
6053
+ minDistance: zoomItem.MinZoom,
6054
+ rendered: (_c = params.rendered) === null || _c === void 0 ? void 0 : _c[entity.Bruce.ID]
5380
6055
  });
5381
6056
  if (!cEntity) return [3 /*break*/, 8];
5382
6057
  return [4 /*yield*/, getName(api, entity)];
5383
6058
  case 7:
5384
- name_4 = _e.sent();
6059
+ name_4 = _f.sent();
5385
6060
  cEntity.name = name_4;
5386
- cEntity._renderGroup = getRenderGroupId(zoomItem, (_c = params.viewer) === null || _c === void 0 ? void 0 : _c.terrainProvider);
6061
+ cEntity._renderGroup = getRenderGroupId(zoomItem, (_d = params.viewer) === null || _d === void 0 ? void 0 : _d.terrainProvider);
5387
6062
  cEntities[entity.Bruce.ID] = cEntity;
5388
- _e.label = 8;
6063
+ _f.label = 8;
5389
6064
  case 8:
5390
6065
  i++;
5391
6066
  return [3 /*break*/, 1];
@@ -5449,22 +6124,99 @@ var EntityRenderEngine;
5449
6124
  color = colorToCColor(bColor);
5450
6125
  }
5451
6126
  }
5452
- var cEntity = new Entity({
6127
+ /*
6128
+ const cEntity: ICesiumEntityExt = new Cesium.Entity({
5453
6129
  id: ObjectUtils.UId(10),
5454
6130
  model: {
5455
6131
  uri: params.lodUrl,
5456
6132
  heightReference: heightRef,
5457
6133
  scale: scale * styleScale,
5458
- shadows: ShadowMode.ENABLED,
6134
+ shadows: Cesium.ShadowMode.ENABLED,
5459
6135
  colorBlendAmount: blendAmount,
5460
6136
  colorBlendMode: blendMode,
5461
- color: color,
6137
+ color: new Cesium.CallbackProperty(() => color, true),
5462
6138
  distanceDisplayCondition: getDisplayCondition(params.minDistance, params.maxDistance)
5463
6139
  },
5464
- orientation: new ConstantProperty(orientation),
6140
+ orientation: new Cesium.ConstantProperty(orientation),
5465
6141
  position: pos,
5466
6142
  show: true
5467
6143
  });
6144
+ */
6145
+ var animateScale = null;
6146
+ var cEntity = params.rendered;
6147
+ if (!cEntity || !cEntity.model) {
6148
+ cEntity = new Entity({
6149
+ id: ObjectUtils.UId(10),
6150
+ model: {
6151
+ uri: params.lodUrl,
6152
+ heightReference: heightRef,
6153
+ scale: new CallbackProperty(function () { return scale * styleScale; }, true),
6154
+ shadows: ShadowMode.ENABLED,
6155
+ colorBlendAmount: blendAmount,
6156
+ colorBlendMode: blendMode,
6157
+ color: new CallbackProperty(function () { return color; }, true),
6158
+ distanceDisplayCondition: getDisplayCondition(params.minDistance, params.maxDistance)
6159
+ },
6160
+ orientation: new ConstantProperty(orientation),
6161
+ position: pos,
6162
+ show: true
6163
+ });
6164
+ }
6165
+ else {
6166
+ // Gather entity in case previous version had sibling graphics we no longer need.
6167
+ var parts = EntityUtils.GatherEntity({
6168
+ entity: cEntity,
6169
+ });
6170
+ if (parts.length > 1) {
6171
+ // Kill all expect last part. Last one is the primary entity.
6172
+ for (var i = 0; i < parts.length - 1; i++) {
6173
+ var part = parts[i];
6174
+ if (part && part instanceof Entity && params.viewer.entities.contains(part)) {
6175
+ params.viewer.entities.remove(part);
6176
+ }
6177
+ }
6178
+ cEntity._siblingGraphics = [];
6179
+ if (cEntity._parentEntity) {
6180
+ console.warn("Model3d.Render: Parent entity was not null. This should not happen.");
6181
+ }
6182
+ }
6183
+ var currentUri = getValue$1(params.viewer, cEntity.model.uri);
6184
+ if (currentUri != params.lodUrl) {
6185
+ cEntity.model.uri = new ConstantProperty(params.lodUrl);
6186
+ }
6187
+ cEntity.model.heightReference = new ConstantProperty(heightRef);
6188
+ cEntity.model.shadows = new ConstantProperty(ShadowMode.ENABLED);
6189
+ cEntity.model.colorBlendAmount = new ConstantProperty(blendAmount);
6190
+ cEntity.model.colorBlendMode = new ConstantProperty(blendMode);
6191
+ cEntity.model.distanceDisplayCondition = new ConstantProperty(getDisplayCondition(params.minDistance, params.maxDistance));
6192
+ cEntity.orientation = new ConstantProperty(orientation);
6193
+ cEntity.position = new ConstantPositionProperty(pos);
6194
+ // Same file but different scale. We'll animate the scale.
6195
+ var prevClientFileId = cEntity.model._clientFileId;
6196
+ if (prevClientFileId == params.lodClientFileId) {
6197
+ animateScale = new CesiumAnimatedProperty.AnimateNumber({
6198
+ durationMs: 200,
6199
+ value: scale * styleScale,
6200
+ viewer: params.viewer,
6201
+ startValue: cEntity.model.scale,
6202
+ startPaused: true
6203
+ });
6204
+ cEntity.model.scale = new CallbackProperty(function () { return animateScale.GetValue(); }, false);
6205
+ }
6206
+ else {
6207
+ cEntity.model.scale = new CallbackProperty(function () { return scale * styleScale; }, true);
6208
+ }
6209
+ // We'll use "SetDefaultColor" to updating the internal reference and to allow for an animation.
6210
+ // cEntity.model.color = new Cesium.CallbackProperty(() => color, true);
6211
+ CesiumEntityStyler.SetDefaultColor({
6212
+ color: color,
6213
+ entity: cEntity,
6214
+ viewer: params.viewer,
6215
+ override: true,
6216
+ requestRender: false
6217
+ });
6218
+ cEntity.show = true;
6219
+ }
5468
6220
  var fileRadiusKey = "model3d_".concat(params.lodUrl, "_").concat(scale * styleScale, "_radius");
5469
6221
  var heightProm = _fileRadiusCache.Get(fileRadiusKey);
5470
6222
  if (!heightProm) {
@@ -5543,6 +6295,10 @@ var EntityRenderEngine;
5543
6295
  VisualRegisterCuller.MarkShouldRecheck(params.viewer);
5544
6296
  }
5545
6297
  }
6298
+ // Rough estimate on when the model is ready in the scene.
6299
+ if (animateScale) {
6300
+ animateScale.Play();
6301
+ }
5546
6302
  });
5547
6303
  var model = cEntity.model;
5548
6304
  model._radiusLoaded = false;
@@ -5555,16 +6311,16 @@ var EntityRenderEngine;
5555
6311
  }
5556
6312
  Model3d.Render = Render;
5557
6313
  function RenderGroup(params) {
5558
- var _a, _b, _c, _d, _e;
6314
+ var _a, _b, _c, _d, _e, _f;
5559
6315
  return __awaiter(this, void 0, void 0, function () {
5560
- var api, cEntities, reqBody, i, entity, zoomItem, style, _f, tagIds, tags, mStyle, group, level, catId, lodData, _loop_2, i;
5561
- return __generator(this, function (_g) {
5562
- switch (_g.label) {
6316
+ var api, cEntities, reqBody, i, entity, zoomItem, style, _g, tagIds, tags, mStyle, group, level, catId, lodData, _loop_2, i;
6317
+ return __generator(this, function (_h) {
6318
+ switch (_h.label) {
5563
6319
  case 0:
5564
6320
  api = params.apiGetter.getApi();
5565
6321
  return [4 /*yield*/, api.Loading];
5566
6322
  case 1:
5567
- _g.sent();
6323
+ _h.sent();
5568
6324
  cEntities = {};
5569
6325
  reqBody = {
5570
6326
  "strict": false,
@@ -5572,7 +6328,7 @@ var EntityRenderEngine;
5572
6328
  "Items": []
5573
6329
  };
5574
6330
  i = 0;
5575
- _g.label = 2;
6331
+ _h.label = 2;
5576
6332
  case 2:
5577
6333
  if (!(i < params.entities.length)) return [3 /*break*/, 9];
5578
6334
  entity = params.entities[i];
@@ -5580,13 +6336,13 @@ var EntityRenderEngine;
5580
6336
  if (!(zoomItem.StyleID != -1)) return [3 /*break*/, 4];
5581
6337
  return [4 /*yield*/, getStyle(api, entity, zoomItem.StyleID)];
5582
6338
  case 3:
5583
- _f = (_a = (_g.sent())) === null || _a === void 0 ? void 0 : _a.Settings;
6339
+ _g = (_a = (_h.sent())) === null || _a === void 0 ? void 0 : _a.Settings;
5584
6340
  return [3 /*break*/, 5];
5585
6341
  case 4:
5586
- _f = zoomItem.Style;
5587
- _g.label = 5;
6342
+ _g = zoomItem.Style;
6343
+ _h.label = 5;
5588
6344
  case 5:
5589
- style = _f;
6345
+ style = _g;
5590
6346
  tagIds = entity.Bruce["Layer.ID"];
5591
6347
  tags = [];
5592
6348
  if (!(tagIds && tagIds.length > 0)) return [3 /*break*/, 7];
@@ -5595,8 +6351,8 @@ var EntityRenderEngine;
5595
6351
  tagIds: tagIds
5596
6352
  })];
5597
6353
  case 6:
5598
- tags = (_g.sent()).tags;
5599
- _g.label = 7;
6354
+ tags = (_h.sent()).tags;
6355
+ _h.label = 7;
5600
6356
  case 7:
5601
6357
  mStyle = (_b = style === null || style === void 0 ? void 0 : style.modelStyle) !== null && _b !== void 0 ? _b : {};
5602
6358
  group = mStyle.lodGroup ? Calculator.GetString(mStyle.lodGroup, entity, tags) : null;
@@ -5617,7 +6373,7 @@ var EntityRenderEngine;
5617
6373
  "group": group,
5618
6374
  "level": level
5619
6375
  });
5620
- _g.label = 8;
6376
+ _h.label = 8;
5621
6377
  case 8:
5622
6378
  i++;
5623
6379
  return [3 /*break*/, 2];
@@ -5626,24 +6382,24 @@ var EntityRenderEngine;
5626
6382
  filter: reqBody
5627
6383
  })];
5628
6384
  case 10:
5629
- lodData = (_g.sent()).lods;
6385
+ lodData = (_h.sent()).lods;
5630
6386
  _loop_2 = function (i) {
5631
- var entity, zoomItem, style, _h, tagIds, tags, lod, mStyle, cEntity, name_5;
5632
- return __generator(this, function (_j) {
5633
- switch (_j.label) {
6387
+ var entity, zoomItem, style, _j, tagIds, tags, lod, mStyle, cEntity, name_5;
6388
+ return __generator(this, function (_k) {
6389
+ switch (_k.label) {
5634
6390
  case 0:
5635
6391
  entity = params.entities[i];
5636
6392
  zoomItem = params.zoomItems[entity.Bruce.ID];
5637
6393
  if (!(zoomItem.StyleID != -1)) return [3 /*break*/, 2];
5638
6394
  return [4 /*yield*/, getStyle(api, entity, zoomItem.StyleID)];
5639
6395
  case 1:
5640
- _h = (_c = (_j.sent())) === null || _c === void 0 ? void 0 : _c.Settings;
6396
+ _j = (_c = (_k.sent())) === null || _c === void 0 ? void 0 : _c.Settings;
5641
6397
  return [3 /*break*/, 3];
5642
6398
  case 2:
5643
- _h = zoomItem.Style;
5644
- _j.label = 3;
6399
+ _j = zoomItem.Style;
6400
+ _k.label = 3;
5645
6401
  case 3:
5646
- style = _h;
6402
+ style = _j;
5647
6403
  tagIds = entity.Bruce["Layer.ID"];
5648
6404
  tags = [];
5649
6405
  if (!(tagIds && tagIds.length > 0)) return [3 /*break*/, 5];
@@ -5652,8 +6408,8 @@ var EntityRenderEngine;
5652
6408
  tagIds: tagIds
5653
6409
  })];
5654
6410
  case 4:
5655
- tags = (_j.sent()).tags;
5656
- _j.label = 5;
6411
+ tags = (_k.sent()).tags;
6412
+ _k.label = 5;
5657
6413
  case 5:
5658
6414
  lod = lodData.find(function (x) { return x.entityId == entity.Bruce.ID; });
5659
6415
  if (!(lod === null || lod === void 0 ? void 0 : lod.clientFileId)) {
@@ -5661,6 +6417,7 @@ var EntityRenderEngine;
5661
6417
  }
5662
6418
  mStyle = (_d = style === null || style === void 0 ? void 0 : style.modelStyle) !== null && _d !== void 0 ? _d : {};
5663
6419
  cEntity = Render({
6420
+ rendered: (_e = params.rendered) === null || _e === void 0 ? void 0 : _e[entity.Bruce.ID],
5664
6421
  entity: entity,
5665
6422
  style: mStyle,
5666
6423
  tags: tags,
@@ -5677,23 +6434,23 @@ var EntityRenderEngine;
5677
6434
  if (!cEntity) return [3 /*break*/, 7];
5678
6435
  return [4 /*yield*/, getName(api, entity)];
5679
6436
  case 6:
5680
- name_5 = _j.sent();
6437
+ name_5 = _k.sent();
5681
6438
  cEntity.name = name_5;
5682
- cEntity._renderGroup = getRenderGroupId(zoomItem, (_e = params.viewer) === null || _e === void 0 ? void 0 : _e.terrainProvider);
6439
+ cEntity._renderGroup = getRenderGroupId(zoomItem, (_f = params.viewer) === null || _f === void 0 ? void 0 : _f.terrainProvider);
5683
6440
  cEntities[entity.Bruce.ID] = cEntity;
5684
- _j.label = 7;
6441
+ _k.label = 7;
5685
6442
  case 7: return [2 /*return*/];
5686
6443
  }
5687
6444
  });
5688
6445
  };
5689
6446
  i = 0;
5690
- _g.label = 11;
6447
+ _h.label = 11;
5691
6448
  case 11:
5692
6449
  if (!(i < params.entities.length)) return [3 /*break*/, 14];
5693
6450
  return [5 /*yield**/, _loop_2(i)];
5694
6451
  case 12:
5695
- _g.sent();
5696
- _g.label = 13;
6452
+ _h.sent();
6453
+ _h.label = 13;
5697
6454
  case 13:
5698
6455
  i++;
5699
6456
  return [3 /*break*/, 11];
@@ -11798,6 +12555,16 @@ var TilesetRenderEngine;
11798
12555
  };
11799
12556
  Styler.prototype.QueueEntities = function (entities, highPriority) {
11800
12557
  if (highPriority === void 0) { highPriority = false; }
12558
+ // We set a default colour right away to avoid race conditions at later times.
12559
+ for (var i = 0; i < entities.length; i++) {
12560
+ var entity = entities[i];
12561
+ this.styledEntityIds[entity.entityId] = true;
12562
+ CesiumEntityStyler.BakeDefaultColor({
12563
+ entity: entity.visual,
12564
+ viewer: this.viewer,
12565
+ override: false
12566
+ });
12567
+ }
11801
12568
  for (var i = 0; i < entities.length; i++) {
11802
12569
  var entity = entities[i];
11803
12570
  this.queueTilesetFeatureStyle(entity, highPriority);
@@ -22578,7 +23345,7 @@ var ViewRenderEngine;
22578
23345
  ViewRenderEngine.Render = Render;
22579
23346
  })(ViewRenderEngine || (ViewRenderEngine = {}));
22580
23347
 
22581
- var VERSION = "3.7.3";
23348
+ var VERSION = "3.7.4";
22582
23349
 
22583
23350
  export { VERSION, CesiumViewMonitor, ViewerUtils, MenuItemManager, EntityRenderEngine, MenuItemCreator, VisualsRegister, RenderManager, EntitiesIdsRenderManager, EntitiesLoadedRenderManager, EntitiesRenderManager, EntityRenderManager, TilesetCadRenderManager, TilesetArbRenderManager, TilesetEntitiesRenderManager, TilesetOsmRenderManager, TilesetPointcloudRenderManager, TilesetGooglePhotosRenderManager, DataSourceStaticKmlManager, RelationsRenderManager, SharedGetters, CesiumParabola, EntityLabel, ViewRenderEngine, TileRenderEngine, TilesetRenderEngine, CESIUM_INSPECTOR_KEY, CESIUM_TIMELINE_KEY, ViewUtils, DrawingUtils, MeasureUtils, EntityUtils, CesiumEntityStyler, Draw3dPolygon, Draw3dPolyline };
22584
23351
  //# sourceMappingURL=bruce-cesium.es5.js.map