bruce-cesium 7.1.5 → 7.1.7

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 * as Cesium from 'cesium';
2
- import { Cartographic, ColorMaterialProperty, Entity, Color, ConstantProperty, CallbackProperty, Primitive, Cesium3DTileFeature, DistanceDisplayCondition, ShaderSource, Cartesian3, Math as Math$1, Ellipsoid, Transforms, Matrix4, Geometry, GeometryAttribute, ComponentDatatype, PrimitiveType, BoundingSphere, GeometryPipeline, sampleTerrain, Texture, PixelFormat, Sampler, TextureWrap, TextureMinificationFilter, TextureMagnificationFilter, VertexArray, BufferUsage, ShaderProgram, RenderState, BlendingState, DrawCommand, Pass, Cartesian2, HeightReference, HorizontalOrigin, VerticalOrigin, ClassificationType, ConstantPositionProperty, ArcType, CornerType, ShadowMode, ColorBlendMode, HeadingPitchRoll, Model, JulianDate, Quaternion, ImageMaterialProperty, PolygonHierarchy, PolylineGraphics, Rectangle, SceneTransforms, NearFarScalar, Matrix3, KmlDataSource, GeoJsonDataSource, SceneMode, Ion, IonResource, Cesium3DTileStyle, HeadingPitchRange, Cesium3DTileColorBlendMode, OrthographicFrustum, EasingFunction, EllipsoidTerrainProvider, IonImageryProvider, createWorldImagery, createWorldImageryAsync, BingMapsImageryProvider, BingMapsStyle, MapboxImageryProvider, MapboxStyleImageryProvider, ArcGisMapServerImageryProvider, OpenStreetMapImageryProvider, UrlTemplateImageryProvider, GridImageryProvider, GeographicTilingScheme, ImageryLayer, TileMapServiceImageryProvider, CesiumTerrainProvider, Cesium3DTileset, Intersect, ModelGraphics, PolygonGraphics, CorridorGraphics, PointGraphics, BillboardGraphics, EllipseGraphics, PolylineDashMaterialProperty, EllipsoidGeodesic, sampleTerrainMostDetailed, defined, CustomDataSource, PolygonPipeline, CesiumInspector, ClockRange, GeometryInstance, ScreenSpaceEventHandler, ScreenSpaceEventType, Fullscreen, CzmlDataSource } from 'cesium';
3
- import { Cartes, Entity as Entity$1, ENVIRONMENT, Api, Calculator, ClientFile, EntityTag, EntityType, LRUCache, ObjectUtils, Style, Carto, Geometry as Geometry$1, EntityLod, MenuItem, ProjectView, ProjectViewBookmark, Tileset, ZoomControl, Bounds, Color as Color$1, BruceEvent, EntityCoords, DataLab, DelayQueue, EntityHistoricData, BruceApi, AccountConcept, RecordChangeFeed, EntityRelation, ProgramKey, EntitySource, Camera, ProjectViewTile, ProjectViewLegacyTile, Account, AccountLimits, Session, UrlUtils, ProjectViewBookmarkGroup, EntityAttachment, EntityAttachmentType, EntityAttribute, MathUtils, EntityRelationType } from 'bruce-models';
2
+ import { Cartographic, ColorMaterialProperty, Entity, Color, ConstantProperty, CallbackProperty, Primitive, Cesium3DTileFeature, ShaderSource, Cartesian3, Math as Math$1, Ellipsoid, Transforms, Matrix4, Geometry, GeometryAttribute, ComponentDatatype, PrimitiveType, BoundingSphere, GeometryPipeline, sampleTerrain, Texture, PixelFormat, Sampler, TextureWrap, TextureMinificationFilter, TextureMagnificationFilter, VertexArray, BufferUsage, ShaderProgram, RenderState, BlendingState, DrawCommand, Pass, Cartesian2, DistanceDisplayCondition, HeightReference, ColorBlendMode, HeadingPitchRoll, ShadowMode, ClassificationType, Model, HorizontalOrigin, VerticalOrigin, ConstantPositionProperty, JulianDate, Quaternion, ArcType, CornerType, ImageMaterialProperty, PolygonHierarchy, PolylineGraphics, Rectangle, SceneTransforms, NearFarScalar, Matrix3, KmlDataSource, GeoJsonDataSource, SceneMode, Cesium3DTileStyle, HeadingPitchRange, Ion, IonResource, Cesium3DTileColorBlendMode, EllipsoidTerrainProvider, IonImageryProvider, createWorldImagery, createWorldImageryAsync, BingMapsImageryProvider, BingMapsStyle, MapboxImageryProvider, MapboxStyleImageryProvider, ArcGisMapServerImageryProvider, OpenStreetMapImageryProvider, UrlTemplateImageryProvider, GridImageryProvider, GeographicTilingScheme, ImageryLayer, TileMapServiceImageryProvider, CesiumTerrainProvider, Cesium3DTileset, OrthographicFrustum, EasingFunction, Intersect, CustomDataSource, EllipsoidGeodesic, sampleTerrainMostDetailed, defined, PolygonPipeline, ModelGraphics, PolygonGraphics, CorridorGraphics, PointGraphics, BillboardGraphics, EllipseGraphics, PolylineDashMaterialProperty, CesiumInspector, ClockRange, GeometryInstance, ScreenSpaceEventHandler, ScreenSpaceEventType, Fullscreen, CzmlDataSource } from 'cesium';
3
+ import { Cartes, Entity as Entity$1, ProjectViewTile, ENVIRONMENT, Calculator, ClientFile, EntityLod, EntityTag, EntityType, LRUCache, ObjectUtils, Style, Api, Carto, Geometry as Geometry$1, MenuItem, ProjectView, ProjectViewBookmark, Tileset, ZoomControl, Bounds, Color as Color$1, BruceEvent, EntityCoords, DataLab, DelayQueue, EntityHistoricData, AccountConcept, RecordChangeFeed, BruceApi, EntityRelation, ProgramKey, EntitySource, ProjectViewLegacyTile, Camera, Account, AccountLimits, Session, UrlUtils, EntityAttachment, EntityAttachmentType, EntityAttribute, MathUtils, ProjectViewBookmarkGroup, EntityRelationType } from 'bruce-models';
4
4
 
5
5
  /**
6
6
  * Ensures a number is returned from a given value.
@@ -2674,184 +2674,909 @@ var CesiumEntityStyler;
2674
2674
  CesiumEntityStyler.Unhighlight = Unhighlight;
2675
2675
  })(CesiumEntityStyler || (CesiumEntityStyler = {}));
2676
2676
 
2677
+ function OnNextCRender(viewer, callback) {
2678
+ const removal = viewer.scene.postRender.addEventListener(() => {
2679
+ removal();
2680
+ callback();
2681
+ });
2682
+ }
2683
+ function GetCValue(viewer, obj) {
2684
+ if (obj === null || obj === void 0 ? void 0 : obj.getValue) {
2685
+ let date = viewer.scene.lastRenderTime;
2686
+ if (!date) {
2687
+ date = viewer.clock.currentTime;
2688
+ }
2689
+ return obj.getValue(date);
2690
+ }
2691
+ return obj;
2692
+ }
2693
+ /*
2694
+ * Marks an EntityCollection as one this library created and fully controls (a menu item's own data source).
2695
+ */
2696
+ const OWNED_CCOLLECTION_KEY = "_bruceOwnedCollection";
2697
+ function MarkCCollectionOwned(collection) {
2698
+ if (collection) {
2699
+ collection[OWNED_CCOLLECTION_KEY] = true;
2700
+ }
2701
+ }
2702
+ function IsCCollectionOwned(collection) {
2703
+ return Boolean(collection && collection[OWNED_CCOLLECTION_KEY]);
2704
+ }
2677
2705
  /**
2678
- * Describes a Nextspace provided UI widget.
2706
+ * Runs a bulk collection mutation with every given collection's events suspended, so Cesium raises one
2707
+ * collectionChanged per collection for the whole pass instead of one per entity.
2708
+ *
2709
+ * Takes a set of collections rather than assuming `viewer.entities`, because managed visuals live in their menu
2710
+ * item's own data source: suspending the wrong collection silently does nothing.
2711
+ * @param collections Duplicates and empty entries are ignored.
2712
+ * @param run
2679
2713
  */
2680
- var Widget;
2681
- (function (Widget) {
2682
- class AWidget {
2683
- get WidgetId() {
2684
- return this.widgetId;
2685
- }
2686
- get Viewer() {
2687
- return this._viewer;
2688
- }
2689
- get Container() {
2690
- return this._container;
2691
- }
2692
- get Element() {
2693
- return this._element;
2694
- }
2695
- constructor(params) {
2696
- this.widgetId = ObjectUtils.UId();
2697
- let { viewer, container, manager } = params;
2698
- // A host app can pass an undefined viewer (eg. mid-teardown); fall back to
2699
- // no container rather than crashing on viewer.container.
2700
- if (!container && viewer) {
2701
- container = viewer.container;
2702
- }
2703
- this._viewer = viewer;
2704
- this._manager = manager;
2705
- this._container = container;
2706
- this._apiGetters = params.apiGetters;
2707
- if (viewer) {
2708
- markViewerWithWidget(viewer, this.widgetId, this);
2709
- }
2714
+ function WithSuspendedCCollections(collections, run) {
2715
+ const unique = [];
2716
+ for (const collection of collections) {
2717
+ if (collection && unique.indexOf(collection) === -1) {
2718
+ unique.push(collection);
2710
2719
  }
2711
- Dispose() {
2712
- if (this._element && this._element.parentElement) {
2713
- this._element.parentElement.removeChild(this._element);
2720
+ }
2721
+ for (const collection of unique) {
2722
+ collection.suspendEvents();
2723
+ }
2724
+ try {
2725
+ return run();
2726
+ }
2727
+ finally {
2728
+ for (const collection of unique) {
2729
+ try {
2730
+ collection.resumeEvents();
2714
2731
  }
2715
- if (this._viewer) {
2716
- unmarkViewerWithWidget(this._viewer, this.widgetId, this);
2732
+ catch (e) {
2733
+ console.error(e);
2717
2734
  }
2718
2735
  }
2719
2736
  }
2720
- Widget.AWidget = AWidget;
2721
- function GetWidgets(viewer) {
2722
- if (viewer && viewer["_nextspaceWidgets"]) {
2723
- return Object.values(viewer["_nextspaceWidgets"]);
2724
- }
2725
- return [];
2737
+ }
2738
+ /**
2739
+ * Returns the collection a graphic belongs to, falling back to the viewer's own when it has never been added.
2740
+ * @param viewer
2741
+ * @param entity
2742
+ */
2743
+ function GetCEntityCollection(viewer, entity) {
2744
+ const owner = entity === null || entity === void 0 ? void 0 : entity.entityCollection;
2745
+ return owner ? owner : viewer === null || viewer === void 0 ? void 0 : viewer.entities;
2746
+ }
2747
+ /**
2748
+ * Returns whether a graphic is currently in the scene, looking in whichever collection owns it.
2749
+ * @param viewer
2750
+ * @param entity
2751
+ */
2752
+ function IsCEntityInScene(viewer, entity) {
2753
+ const collection = GetCEntityCollection(viewer, entity);
2754
+ return Boolean(collection && entity && collection.contains(entity));
2755
+ }
2756
+ /**
2757
+ * Removes a graphic from whichever collection owns it. Returns whether it removed anything.
2758
+ * @param viewer
2759
+ * @param entity
2760
+ */
2761
+ function RemoveCEntityFromScene(viewer, entity) {
2762
+ var _a;
2763
+ if (!entity) {
2764
+ return false;
2726
2765
  }
2727
- Widget.GetWidgets = GetWidgets;
2728
- })(Widget || (Widget = {}));
2729
- function markViewerWithWidget(viewer, widgetId, widget) {
2730
- if (!viewer["_nextspaceWidgets"]) {
2731
- viewer["_nextspaceWidgets"] = {};
2766
+ const collection = GetCEntityCollection(viewer, entity);
2767
+ if (collection === null || collection === void 0 ? void 0 : collection.contains(entity)) {
2768
+ return collection.remove(entity);
2732
2769
  }
2733
- viewer["_nextspaceWidgets"][widgetId] = widget;
2770
+ // A stale owner reference and the graphic ended up in the viewer's collection anyway.
2771
+ if (collection !== (viewer === null || viewer === void 0 ? void 0 : viewer.entities) && ((_a = viewer === null || viewer === void 0 ? void 0 : viewer.entities) === null || _a === void 0 ? void 0 : _a.contains(entity))) {
2772
+ return viewer.entities.remove(entity);
2773
+ }
2774
+ return false;
2734
2775
  }
2735
- function unmarkViewerWithWidget(viewer, widgetId, widget) {
2736
- if (viewer["_nextspaceWidgets"]) {
2737
- delete viewer["_nextspaceWidgets"][widgetId];
2776
+ /**
2777
+ * Adds a graphic back into whichever collection owns it, or the viewer's if it has no owner yet.
2778
+ * @param viewer
2779
+ * @param entity
2780
+ */
2781
+ function AddCEntityToScene(viewer, entity, fallbackCollection) {
2782
+ if (!entity) {
2783
+ return false;
2784
+ }
2785
+ // An existing owner always wins, so a graphic is never migrated out from under whoever holds it.
2786
+ const owner = entity.entityCollection;
2787
+ const collection = owner ? owner : (fallbackCollection ? fallbackCollection : viewer === null || viewer === void 0 ? void 0 : viewer.entities);
2788
+ if (!collection || collection.contains(entity)) {
2789
+ return false;
2738
2790
  }
2791
+ collection.add(entity);
2792
+ return true;
2739
2793
  }
2740
-
2741
- var WidgetControlViewBar;
2742
- (function (WidgetControlViewBar) {
2743
- class AControl {
2744
- get WidgetViewBar() {
2745
- return this._widget;
2746
- }
2747
- get Container() {
2748
- return this._container;
2794
+ /**
2795
+ * Returns whether toggling `show` on these graphics is safe, rather than having to add/remove them from the
2796
+ * entity collection to hide them.
2797
+ *
2798
+ * Toggling show is far cheaper than re-adding the graphic to the viewer however a Cesium bug means we can't always use it.
2799
+ * See: https://github.com/CesiumGS/cesium/issues/9370
2800
+ * @param parts The graphic and any sibling graphics, eg. from EntityUtils.GatherEntity.
2801
+ */
2802
+ function CanToggleShowSafely(parts) {
2803
+ if (!(parts === null || parts === void 0 ? void 0 : parts.length)) {
2804
+ return false;
2805
+ }
2806
+ for (const part of parts) {
2807
+ if (!(part instanceof Entity)) {
2808
+ // Not an Entity, so not something whose `show` we can drive.
2809
+ return false;
2749
2810
  }
2750
- get Element() {
2751
- return this._element;
2811
+ if (part.polyline && isTruthyCValue(part.polyline.clampToGround)) {
2812
+ return false;
2752
2813
  }
2753
- get Disposed() {
2754
- return this._disposed;
2814
+ const materialGraphics = [part.polygon, part.corridor, part.ellipse, part.rectangle, part.wall, part.polylineVolume];
2815
+ for (const graphic of materialGraphics) {
2816
+ if (graphic && !isPlainColorMaterial(graphic.material)) {
2817
+ return false;
2818
+ }
2755
2819
  }
2756
- get Enabled() {
2757
- return this._enabled;
2820
+ }
2821
+ return true;
2822
+ }
2823
+ /**
2824
+ * Returns whether a material is a plain colour, which is what keeps a graphic out of Cesium's per-material batches.
2825
+ * Anything unrecognised counts as not plain, so callers stay on the conservative side.
2826
+ * @param material
2827
+ */
2828
+ function isPlainColorMaterial(material) {
2829
+ if (material == null) {
2830
+ // Cesium defaults an absent material to white, a plain colour.
2831
+ return true;
2832
+ }
2833
+ return material instanceof ColorMaterialProperty || material instanceof Color;
2834
+ }
2835
+ /**
2836
+ * Resolves a possibly-property boolean without needing a viewer clock, treating anything undeterminable as true
2837
+ * so callers stay on the conservative side.
2838
+ * @param value
2839
+ */
2840
+ function isTruthyCValue(value) {
2841
+ if (value == null) {
2842
+ return false;
2843
+ }
2844
+ if (typeof value.getValue === "function") {
2845
+ if (value instanceof ConstantProperty) {
2846
+ return Boolean(value.valueOf());
2758
2847
  }
2759
- constructor(params) {
2760
- this._disposed = false;
2761
- this._enabled = false;
2762
- let { container, widget, element } = params;
2763
- this._widget = widget;
2764
- this._container = container;
2765
- this._element = element;
2848
+ // A non-constant property could be true at any moment, so assume it is.
2849
+ return true;
2850
+ }
2851
+ return Boolean(value);
2852
+ }
2853
+ /**
2854
+ * Returns if two resolved Cesium property values are equal, using the value's own equals() when it has one.
2855
+ * @param a
2856
+ * @param b
2857
+ */
2858
+ function AreCValuesEqual(a, b) {
2859
+ if (a === b) {
2860
+ return true;
2861
+ }
2862
+ // One side is null/undefined and the other isn't.
2863
+ if (a == null || b == null) {
2864
+ return false;
2865
+ }
2866
+ if (typeof a.equals === "function") {
2867
+ return a.equals(b) === true;
2868
+ }
2869
+ return false;
2870
+ }
2871
+ /**
2872
+ * Wraps a value in a ConstantProperty and assigns it to a graphic's property, but only when the resolved
2873
+ * value actually differs. Returns whether it assigned.
2874
+ * @param params
2875
+ */
2876
+ function SetCPropIfChanged(params) {
2877
+ const { viewer, graphic, property, value, compare } = params;
2878
+ if (!graphic) {
2879
+ return false;
2880
+ }
2881
+ const oldValue = GetCValue(viewer, graphic[property]);
2882
+ const isEqual = compare ? compare(oldValue, value) : AreCValuesEqual(oldValue, value);
2883
+ if (isEqual) {
2884
+ return false;
2885
+ }
2886
+ graphic[property] = new ConstantProperty(value);
2887
+ return true;
2888
+ }
2889
+ function ColorToCColor(color) {
2890
+ return new Color(color.red ? color.red / 255 : 0, color.green ? color.green / 255 : 0, color.blue ? color.blue / 255 : 0, color.alpha);
2891
+ }
2892
+ /**
2893
+ * Removes duplicate points in a row and returns a new array.
2894
+ * Passed array is not mutated.
2895
+ * @param posses
2896
+ */
2897
+ function CullDuplicateCPosses(posses) {
2898
+ const newPosses = [];
2899
+ let lastPos = null;
2900
+ for (let i = 0; i < posses.length; i++) {
2901
+ const pos = posses[i];
2902
+ // Avoiding 'Cesium.Cartesian3.equals' because passed data might be just a json blob in certain cases.
2903
+ if (pos && (!lastPos || (pos.x != lastPos.x || pos.y != lastPos.y || pos.z != lastPos.z))) {
2904
+ newPosses.push(pos);
2905
+ lastPos = pos;
2766
2906
  }
2767
- Toggle() {
2907
+ }
2908
+ return newPosses;
2909
+ }
2910
+ /**
2911
+ * Returns if the given positions are equal.
2912
+ * @param a
2913
+ * @param b
2914
+ */
2915
+ function CompareCPosses(a, b) {
2916
+ // Same reference.
2917
+ if (a == b) {
2918
+ return true;
2919
+ }
2920
+ // Different lengths or one is null.
2921
+ if ((!a || !b) || (a.length != b.length)) {
2922
+ return false;
2923
+ }
2924
+ for (let i = 0; i < a.length; i++) {
2925
+ const posA = a[i];
2926
+ const posB = b[i];
2927
+ // Null detected.
2928
+ if (!posA || !posB) {
2929
+ return false;
2768
2930
  }
2769
- Dispose() {
2770
- this._disposed = true;
2931
+ // Position values don't match.
2932
+ if (!Cartes.IsEqualCartes3(posA, posB)) {
2933
+ return false;
2771
2934
  }
2772
2935
  }
2773
- WidgetControlViewBar.AControl = AControl;
2774
- })(WidgetControlViewBar || (WidgetControlViewBar = {}));
2775
-
2936
+ return true;
2937
+ }
2776
2938
  /**
2777
- * The fullscreen control is a simple toggle.
2778
- * There is no HTML element. However we do swap the icon based on the toggle state.
2939
+ * Returns if the given polygon hierarchies are equal.
2940
+ * @param a
2941
+ * @param b
2779
2942
  */
2780
- class WidgetControlViewBarFullscreen extends WidgetControlViewBar.AControl {
2781
- constructor(params) {
2782
- super(params);
2943
+ function CompareCPolygonHierarchies(a, b) {
2944
+ // Same reference.
2945
+ if (a == b) {
2946
+ return true;
2783
2947
  }
2784
- Dispose() {
2785
- super.Dispose();
2948
+ // Different lengths or one is null.
2949
+ if ((!a || !b) || (a.positions.length != b.positions.length)) {
2950
+ return false;
2786
2951
  }
2787
- Toggle() {
2788
- if (this.Disposed) {
2789
- return;
2790
- }
2791
- super.Toggle();
2792
- // Toggle fullscreen.
2793
- this._enabled = false;
2794
- if (Fullscreen.enabled) {
2795
- if (Fullscreen.fullscreen) {
2796
- Fullscreen.exitFullscreen();
2797
- }
2798
- else {
2799
- Fullscreen.requestFullscreen(document.body);
2800
- this._enabled = true;
2801
- }
2952
+ // Positions don't match.
2953
+ if (!CompareCPosses(a.positions, b.positions)) {
2954
+ return false;
2955
+ }
2956
+ const holes = a.holes;
2957
+ const bHoles = b.holes;
2958
+ // Number of holes don't match.
2959
+ if (holes.length != bHoles.length) {
2960
+ return false;
2961
+ }
2962
+ for (let i = 0; i < holes.length; i++) {
2963
+ // Hole positions don't match.
2964
+ if (!CompareCPosses(holes[i].positions, bHoles[i].positions)) {
2965
+ return false;
2802
2966
  }
2803
2967
  }
2968
+ return true;
2804
2969
  }
2805
2970
 
2806
- class WidgetControlViewBarSearch extends WidgetControlViewBar.AControl {
2807
- constructor(params) {
2808
- super(params);
2809
- this.STYLESHEET_ID = "nextspace-control-view-bar-searchbar-stylesheet";
2810
- this._generateStyles();
2811
- this._generateElement();
2971
+ const CESIUM_INSPECTOR_KEY = "_nextspace_inspector";
2972
+ const CESIUM_TIMELINE_KEY = "_nextspace_timeline";
2973
+ const CESIUM_TIMELINE_LIVE_KEY = "_nextspace_timeline_live";
2974
+ const CESIUM_TIMELINE_LIVE_PADDING_KEY = "_nextspace_timeline_live_padding";
2975
+ const CESIUM_TIMELINE_INTERVAL_KEY = "_nextspace_timeline_interval";
2976
+ const CESIUM_MODEL_SPACE_KEY = "_nextspace_model_space";
2977
+ const DEFAULT_LIVE_PADDING_SECONDS = 30 * 60;
2978
+ const DEFAULT_BRIGHTNESS_SHIFT = 0.2;
2979
+ var ViewUtils;
2980
+ (function (ViewUtils) {
2981
+ function GatherLegacyMapTiles(params) {
2982
+ const viewer = params.viewer;
2983
+ const collection = viewer.imageryLayers;
2984
+ const tiles = [];
2985
+ for (let i = 0; i < collection.length; i++) {
2986
+ const layer = collection.get(i);
2987
+ if (layer._bName) {
2988
+ tiles.push({
2989
+ alpha: layer.alpha,
2990
+ brightness: layer.brightness,
2991
+ contrast: layer.contrast,
2992
+ hue: layer.hue,
2993
+ saturation: layer.saturation,
2994
+ gamma: layer.gamma,
2995
+ title: layer._bName,
2996
+ });
2997
+ }
2998
+ }
2999
+ return {
3000
+ imagery: tiles.reverse()
3001
+ };
2812
3002
  }
2813
- Dispose() {
2814
- super.Dispose();
2815
- if (this._element && this._element.parentElement) {
2816
- this._element.parentElement.removeChild(this._element);
3003
+ ViewUtils.GatherLegacyMapTiles = GatherLegacyMapTiles;
3004
+ function GatherLegacyTerrainTile(params) {
3005
+ const viewer = params.viewer;
3006
+ const enabled = viewer.terrainProvider;
3007
+ if (enabled === null || enabled === void 0 ? void 0 : enabled._bName) {
3008
+ return {
3009
+ terrain: enabled._bName
3010
+ };
2817
3011
  }
2818
- if (this._results && this._results.parentElement) {
2819
- this._results.parentElement.removeChild(this._results);
3012
+ return {
3013
+ terrain: "flatterrain"
3014
+ };
3015
+ }
3016
+ ViewUtils.GatherLegacyTerrainTile = GatherLegacyTerrainTile;
3017
+ function GatherMapTiles(params) {
3018
+ const viewer = params.viewer;
3019
+ const imagery = viewer.imageryLayers;
3020
+ const tiles = [];
3021
+ for (let i = 0; i < imagery.length; i++) {
3022
+ const provider = imagery.get(i);
3023
+ if (provider._bMeta) {
3024
+ const idCombo = provider._bMeta.accountId + provider._bMeta.tilesetId;
3025
+ if (!tiles.find(x => x.accountId + x.tilesetId === idCombo)) {
3026
+ tiles.push({
3027
+ accountId: provider._bMeta.accountId,
3028
+ tilesetId: provider._bMeta.tilesetId,
3029
+ alpha: provider.alpha,
3030
+ brightness: provider.brightness,
3031
+ contrast: provider.contrast,
3032
+ hue: provider.hue,
3033
+ saturation: provider.saturation,
3034
+ gamma: provider.gamma
3035
+ });
3036
+ }
3037
+ }
2820
3038
  }
3039
+ return {
3040
+ imagery: tiles
3041
+ };
2821
3042
  }
2822
- Toggle() {
2823
- if (this.Disposed) {
2824
- return;
3043
+ ViewUtils.GatherMapTiles = GatherMapTiles;
3044
+ function GatherTerrainTile(params) {
3045
+ const viewer = params.viewer;
3046
+ const provider = viewer.terrainProvider;
3047
+ if (provider === null || provider === void 0 ? void 0 : provider._bMeta) {
3048
+ return {
3049
+ terrain: {
3050
+ accountId: provider._bMeta.accountId,
3051
+ tilesetId: provider._bMeta.tilesetId,
3052
+ }
3053
+ };
2825
3054
  }
2826
- super.Toggle();
2827
- this._enabled = !this._enabled;
2828
- if (this._enabled) {
2829
- this._display();
3055
+ else if (provider instanceof EllipsoidTerrainProvider) {
3056
+ return {
3057
+ terrain: {
3058
+ tilesetId: ProjectViewTile.EDefaultTerrain.FlatTerrain,
3059
+ accountId: null
3060
+ }
3061
+ };
2830
3062
  }
2831
- else {
2832
- this._hide();
3063
+ return null;
3064
+ }
3065
+ ViewUtils.GatherTerrainTile = GatherTerrainTile;
3066
+ function SetTerrainWireframeStatus(params) {
3067
+ if (!params.viewer[CESIUM_INSPECTOR_KEY]) {
3068
+ const InspectorClass = CesiumInspector;
3069
+ if (InspectorClass) {
3070
+ const inspector = new InspectorClass(document.createElement("div"), params.viewer.scene);
3071
+ inspector.container.style.display = "none";
3072
+ params.viewer[CESIUM_INSPECTOR_KEY] = inspector;
3073
+ params.viewer.scene.requestRender();
3074
+ }
3075
+ }
3076
+ if (params.viewer[CESIUM_INSPECTOR_KEY]) {
3077
+ params.viewer[CESIUM_INSPECTOR_KEY].viewModel.wireframe = params.status;
2833
3078
  }
2834
3079
  }
2835
- _generateStyles() {
2836
- if (document.getElementById(this.STYLESHEET_ID)) {
2837
- return;
3080
+ ViewUtils.SetTerrainWireframeStatus = SetTerrainWireframeStatus;
3081
+ function GetTerrainWireframeStatus(params) {
3082
+ var _a, _b;
3083
+ if (!params.viewer[CESIUM_INSPECTOR_KEY]) {
3084
+ return false;
2838
3085
  }
2839
- const style = document.createElement("style");
2840
- style.id = this.STYLESHEET_ID;
2841
- style.innerHTML = `
2842
- .NextspaceSearchBar {
2843
- display: flex;
2844
- box-sizing: border-box;
2845
- height: 100%;
2846
- font-family: sans-serif;
2847
- }
2848
-
2849
- .NextspaceSearchBar * {
2850
- box-sizing: border-box;
2851
- }
2852
-
2853
- .NextspaceSearchBar[is-opened="true"] .NextspaceSearchBarContent {
2854
- display: flex;
3086
+ return (_b = (_a = params.viewer[CESIUM_INSPECTOR_KEY]) === null || _a === void 0 ? void 0 : _a.viewModel) === null || _b === void 0 ? void 0 : _b.wireframe;
3087
+ }
3088
+ ViewUtils.GetTerrainWireframeStatus = GetTerrainWireframeStatus;
3089
+ /**
3090
+ * Changes between perspective and orthographic view.
3091
+ * When Cesium stops being bad at picking positions in 2d mode we'll use the flat earth mode instead.
3092
+ * @param params
3093
+ */
3094
+ function Set2dStatus(params) {
3095
+ const { viewer, status: is2d, moveCamera } = params;
3096
+ const curLens2d = viewer.camera.frustum instanceof OrthographicFrustum;
3097
+ if (curLens2d && !is2d) {
3098
+ OnNextCRender(viewer, () => {
3099
+ viewer.camera.switchToPerspectiveFrustum();
3100
+ viewer.scene.screenSpaceCameraController.enableTilt = true;
3101
+ });
3102
+ viewer.scene.requestRender();
3103
+ }
3104
+ else if (!curLens2d && is2d) {
3105
+ OnNextCRender(viewer, () => {
3106
+ viewer.camera.switchToOrthographicFrustum();
3107
+ viewer.scene.screenSpaceCameraController.enableTilt = false;
3108
+ });
3109
+ if (moveCamera != false) {
3110
+ try {
3111
+ // Face camera downwards to make it look 2d.
3112
+ // We want to try make it look at the center-point of the current view.
3113
+ // If center cannot be calculated then we'll simply raise the camera and face it downwards.
3114
+ const scene = viewer.scene;
3115
+ const windowPosition = new Cartesian2(scene.canvas.clientWidth / 2, scene.canvas.clientHeight / 2);
3116
+ const ray = viewer.camera.getPickRay(windowPosition);
3117
+ const intersection = scene.globe.pick(ray, scene);
3118
+ let center;
3119
+ if (defined(intersection)) {
3120
+ center = Cartographic.fromCartesian(intersection);
3121
+ }
3122
+ // Use current camera position if we can't calculate the center.
3123
+ else {
3124
+ center = Cartographic.fromCartesian(viewer.camera.position);
3125
+ center.height = 0;
3126
+ }
3127
+ center.height = viewer.camera.positionCartographic.height + 100;
3128
+ viewer.camera.setView({
3129
+ destination: Cartographic.toCartesian(center),
3130
+ orientation: {
3131
+ heading: 0.0,
3132
+ pitch: Math$1.toRadians(-90.0),
3133
+ roll: 0.0
3134
+ }
3135
+ });
3136
+ }
3137
+ catch (e) {
3138
+ console.error(e);
3139
+ }
3140
+ }
3141
+ viewer.scene.requestRender();
3142
+ }
3143
+ }
3144
+ ViewUtils.Set2dStatus = Set2dStatus;
3145
+ function Get2dStatus(params) {
3146
+ const { viewer } = params;
3147
+ return viewer.camera.frustum instanceof OrthographicFrustum;
3148
+ }
3149
+ ViewUtils.Get2dStatus = Get2dStatus;
3150
+ function SetLockedCameraStatus(params) {
3151
+ const { viewer, status } = params;
3152
+ const scene = viewer === null || viewer === void 0 ? void 0 : viewer.scene;
3153
+ if (!scene) {
3154
+ return;
3155
+ }
3156
+ if (status) {
3157
+ scene.screenSpaceCameraController.enableInputs = false;
3158
+ scene.screenSpaceCameraController.enableTranslate = false;
3159
+ scene.screenSpaceCameraController.enableZoom = false;
3160
+ scene.screenSpaceCameraController.enableRotate = false;
3161
+ scene.screenSpaceCameraController.enableTilt = false;
3162
+ }
3163
+ else {
3164
+ scene.screenSpaceCameraController.enableInputs = true;
3165
+ scene.screenSpaceCameraController.enableTranslate = true;
3166
+ scene.screenSpaceCameraController.enableZoom = true;
3167
+ scene.screenSpaceCameraController.enableRotate = true;
3168
+ if (!ViewUtils.Get2dStatus({ viewer })) {
3169
+ scene.screenSpaceCameraController.enableTilt = true;
3170
+ }
3171
+ }
3172
+ viewer.scene.requestRender();
3173
+ }
3174
+ ViewUtils.SetLockedCameraStatus = SetLockedCameraStatus;
3175
+ function GetLockedCameraStatus(params) {
3176
+ var _a;
3177
+ const scene = (_a = params.viewer) === null || _a === void 0 ? void 0 : _a.scene;
3178
+ if (!scene) {
3179
+ return false;
3180
+ }
3181
+ return !scene.screenSpaceCameraController.enableTranslate;
3182
+ }
3183
+ ViewUtils.GetLockedCameraStatus = GetLockedCameraStatus;
3184
+ /**
3185
+ * Returns the current camera time and related settings.
3186
+ * @param params
3187
+ * @returns
3188
+ */
3189
+ function GetTimeDetails(params) {
3190
+ const { viewer } = params;
3191
+ const clock = viewer.clock;
3192
+ return {
3193
+ animationSpeed: clock.multiplier,
3194
+ isAnimating: clock.shouldAnimate,
3195
+ startTime: clock.startTime,
3196
+ startTimeIso: clock.startTime.toString(),
3197
+ currentTime: clock.currentTime,
3198
+ currentTimeIso: clock.currentTime.toString(),
3199
+ stopTime: clock.stopTime,
3200
+ stopTimeIso: clock.stopTime.toString(),
3201
+ areCesiumValues: clock[CESIUM_TIMELINE_KEY] != true,
3202
+ isLive: clock[CESIUM_TIMELINE_LIVE_KEY] == true,
3203
+ livePaddingSeconds: clock[CESIUM_TIMELINE_LIVE_PADDING_KEY] || DEFAULT_LIVE_PADDING_SECONDS
3204
+ };
3205
+ }
3206
+ ViewUtils.GetTimeDetails = GetTimeDetails;
3207
+ /**
3208
+ * Sets the Cesium clock values.
3209
+ * If a value is not provided, then 'areCesiumValues' checked to see if the values are Cesium values.
3210
+ * If they're currently Cesium set values then our defaults are used.
3211
+ * @param params
3212
+ */
3213
+ function SetTimeDetails(params) {
3214
+ let { viewer, animationSpeed, isAnimating, startTime, currentTime, stopTime, startTimeIso, stopTimeIso, currentTimeIso, isLive, livePaddingSeconds } = params;
3215
+ const clock = viewer.clock;
3216
+ if (startTime) {
3217
+ clock.startTime = startTime;
3218
+ }
3219
+ else if (startTimeIso) {
3220
+ const startDate = JulianDate.fromIso8601(startTimeIso);
3221
+ if (startDate) {
3222
+ clock.startTime = startDate;
3223
+ }
3224
+ }
3225
+ if (currentTime) {
3226
+ clock.currentTime = currentTime;
3227
+ }
3228
+ else if (currentTimeIso) {
3229
+ const currentDate = JulianDate.fromIso8601(currentTimeIso);
3230
+ if (currentDate) {
3231
+ clock.currentTime = currentDate;
3232
+ }
3233
+ }
3234
+ if (stopTime) {
3235
+ clock.stopTime = stopTime;
3236
+ }
3237
+ else if (stopTimeIso) {
3238
+ const stopDate = JulianDate.fromIso8601(stopTimeIso);
3239
+ if (stopDate) {
3240
+ clock.stopTime = stopDate;
3241
+ }
3242
+ }
3243
+ clock.clockRange = ClockRange.LOOP_STOP;
3244
+ const areCesiumValues = clock[CESIUM_TIMELINE_KEY] != true;
3245
+ if (areCesiumValues) {
3246
+ if (isNaN(animationSpeed) || animationSpeed == null) {
3247
+ animationSpeed = 1;
3248
+ }
3249
+ if (isAnimating == null) {
3250
+ isAnimating = false;
3251
+ }
3252
+ if (isLive == null) {
3253
+ isLive = false;
3254
+ }
3255
+ if (livePaddingSeconds == null) {
3256
+ livePaddingSeconds = DEFAULT_LIVE_PADDING_SECONDS;
3257
+ }
3258
+ }
3259
+ if (!isNaN(animationSpeed) && animationSpeed != null) {
3260
+ clock.multiplier = animationSpeed;
3261
+ }
3262
+ if (isAnimating != null) {
3263
+ clock.shouldAnimate = isAnimating;
3264
+ }
3265
+ viewer.scene.requestRender();
3266
+ clock[CESIUM_TIMELINE_KEY] = true;
3267
+ if (livePaddingSeconds != null) {
3268
+ clock[CESIUM_TIMELINE_LIVE_PADDING_KEY] = livePaddingSeconds || DEFAULT_LIVE_PADDING_SECONDS;
3269
+ }
3270
+ if (isLive != null) {
3271
+ clock[CESIUM_TIMELINE_LIVE_KEY] = params.isLive == true;
3272
+ }
3273
+ if (clock[CESIUM_TIMELINE_LIVE_KEY]) {
3274
+ startLive(viewer);
3275
+ }
3276
+ else {
3277
+ stopLive(viewer);
3278
+ }
3279
+ }
3280
+ ViewUtils.SetTimeDetails = SetTimeDetails;
3281
+ function startLive(viewer) {
3282
+ const doUpdate = () => {
3283
+ if (!viewer || viewer.isDestroyed() || !viewer.scene) {
3284
+ stopLive(viewer);
3285
+ return;
3286
+ }
3287
+ // Get the current settings.
3288
+ const tDetails = GetTimeDetails({ viewer });
3289
+ const clock = viewer.clock;
3290
+ if (clock) {
3291
+ clock.shouldAnimate = true;
3292
+ clock.multiplier = 1;
3293
+ clock.currentTime = JulianDate.now();
3294
+ clock.startTime = JulianDate.addSeconds(clock.currentTime, -tDetails.livePaddingSeconds, new JulianDate());
3295
+ clock.stopTime = JulianDate.addSeconds(clock.currentTime, tDetails.livePaddingSeconds, new JulianDate());
3296
+ clock.clockRange = ClockRange.UNBOUNDED;
3297
+ }
3298
+ };
3299
+ if (viewer[CESIUM_TIMELINE_INTERVAL_KEY]) {
3300
+ doUpdate();
3301
+ return;
3302
+ }
3303
+ // We'll start an interval that occasionally updates the Cesium clock to stay in the desired settings.
3304
+ // Since it moves live (1 second per second), we don't have to worry about the ranges being out of date quickly.
3305
+ viewer[CESIUM_TIMELINE_INTERVAL_KEY] = setInterval(() => {
3306
+ doUpdate();
3307
+ }, 800);
3308
+ viewer[CESIUM_TIMELINE_LIVE_KEY] = true;
3309
+ // Initial update.
3310
+ doUpdate();
3311
+ }
3312
+ function stopLive(viewer) {
3313
+ if (!viewer) {
3314
+ return;
3315
+ }
3316
+ let interval = viewer[CESIUM_TIMELINE_INTERVAL_KEY];
3317
+ if (interval) {
3318
+ clearInterval(interval);
3319
+ viewer[CESIUM_TIMELINE_INTERVAL_KEY] = null;
3320
+ }
3321
+ viewer[CESIUM_TIMELINE_LIVE_KEY] = false;
3322
+ }
3323
+ /**
3324
+ * Brightens a scene's atmosphere, using whichever control the host app's CesiumJS exposes.
3325
+ * @param viewer the viewer to brighten. Safe to call with null.
3326
+ * @param shift -1 to 1, where 0 or less leaves CesiumJS's own defaults alone.
3327
+ */
3328
+ function ApplyDefaultBrightness(viewer, shift = DEFAULT_BRIGHTNESS_SHIFT) {
3329
+ const scene = viewer === null || viewer === void 0 ? void 0 : viewer.scene;
3330
+ if (!scene || !(shift > 0)) {
3331
+ return;
3332
+ }
3333
+ // Atmosphere settings moved from Globe onto Scene, and the sky keeps its own copy, so each is
3334
+ // probed rather than version checked: host apps bring their own CesiumJS.
3335
+ const SCENE = scene;
3336
+ if (SCENE.atmosphere && typeof SCENE.atmosphere.brightnessShift === "number") {
3337
+ SCENE.atmosphere.brightnessShift = shift;
3338
+ }
3339
+ if (SCENE.globe && typeof SCENE.globe.atmosphereBrightnessShift === "number") {
3340
+ SCENE.globe.atmosphereBrightnessShift = shift;
3341
+ }
3342
+ if (SCENE.skyAtmosphere && typeof SCENE.skyAtmosphere.brightnessShift === "number") {
3343
+ SCENE.skyAtmosphere.brightnessShift = shift;
3344
+ }
3345
+ }
3346
+ ViewUtils.ApplyDefaultBrightness = ApplyDefaultBrightness;
3347
+ function SetGlobeDetails(params) {
3348
+ let { viewer, hidden, baseColor } = params;
3349
+ const scene = viewer === null || viewer === void 0 ? void 0 : viewer.scene;
3350
+ if (!(scene === null || scene === void 0 ? void 0 : scene.globe)) {
3351
+ return;
3352
+ }
3353
+ if (hidden == null) {
3354
+ hidden = !scene.globe.show;
3355
+ }
3356
+ else {
3357
+ scene.globe.show = !hidden;
3358
+ }
3359
+ if (baseColor == null) {
3360
+ baseColor = scene.globe.baseColor;
3361
+ }
3362
+ // When globe is off, we'll also hide the stars/moon.
3363
+ // We also grab the globe color and apply it to the sky.
3364
+ if (hidden && GetModelSpace(viewer)) {
3365
+ scene.skyBox.show = false;
3366
+ scene.skyAtmosphere.show = false;
3367
+ scene.sun.show = false;
3368
+ scene.moon.show = false;
3369
+ scene.backgroundColor = baseColor.clone();
3370
+ }
3371
+ else {
3372
+ scene.skyBox.show = true;
3373
+ scene.skyAtmosphere.show = true;
3374
+ scene.sun.show = true;
3375
+ scene.moon.show = true;
3376
+ scene.backgroundColor = Color.BLACK;
3377
+ }
3378
+ scene.globe.baseColor = baseColor;
3379
+ }
3380
+ ViewUtils.SetGlobeDetails = SetGlobeDetails;
3381
+ function SetModelSpace(viewer, modelSpace) {
3382
+ if (!viewer) {
3383
+ return;
3384
+ }
3385
+ if (viewer[CESIUM_MODEL_SPACE_KEY] === modelSpace) {
3386
+ return;
3387
+ }
3388
+ viewer[CESIUM_MODEL_SPACE_KEY] = modelSpace;
3389
+ // Reload globe since we display it differently between the two modes.
3390
+ SetGlobeDetails({ viewer });
3391
+ }
3392
+ ViewUtils.SetModelSpace = SetModelSpace;
3393
+ function GetModelSpace(viewer) {
3394
+ if (!viewer) {
3395
+ return false;
3396
+ }
3397
+ return Boolean(viewer[CESIUM_MODEL_SPACE_KEY]);
3398
+ }
3399
+ ViewUtils.GetModelSpace = GetModelSpace;
3400
+ })(ViewUtils || (ViewUtils = {}));
3401
+
3402
+ /**
3403
+ * Describes a Nextspace provided UI widget.
3404
+ */
3405
+ var Widget;
3406
+ (function (Widget) {
3407
+ class AWidget {
3408
+ get WidgetId() {
3409
+ return this.widgetId;
3410
+ }
3411
+ get Viewer() {
3412
+ return this._viewer;
3413
+ }
3414
+ get Container() {
3415
+ return this._container;
3416
+ }
3417
+ get Element() {
3418
+ return this._element;
3419
+ }
3420
+ constructor(params) {
3421
+ this.widgetId = ObjectUtils.UId();
3422
+ let { viewer, container, manager } = params;
3423
+ // A host app can pass an undefined viewer (eg. mid-teardown); fall back to
3424
+ // no container rather than crashing on viewer.container.
3425
+ if (!container && viewer) {
3426
+ container = viewer.container;
3427
+ }
3428
+ this._viewer = viewer;
3429
+ this._manager = manager;
3430
+ this._container = container;
3431
+ this._apiGetters = params.apiGetters;
3432
+ if (viewer) {
3433
+ markViewerWithWidget(viewer, this.widgetId, this);
3434
+ }
3435
+ }
3436
+ Dispose() {
3437
+ if (this._element && this._element.parentElement) {
3438
+ this._element.parentElement.removeChild(this._element);
3439
+ }
3440
+ if (this._viewer) {
3441
+ unmarkViewerWithWidget(this._viewer, this.widgetId, this);
3442
+ }
3443
+ }
3444
+ }
3445
+ Widget.AWidget = AWidget;
3446
+ function GetWidgets(viewer) {
3447
+ if (viewer && viewer["_nextspaceWidgets"]) {
3448
+ return Object.values(viewer["_nextspaceWidgets"]);
3449
+ }
3450
+ return [];
3451
+ }
3452
+ Widget.GetWidgets = GetWidgets;
3453
+ })(Widget || (Widget = {}));
3454
+ function markViewerWithWidget(viewer, widgetId, widget) {
3455
+ if (!viewer["_nextspaceWidgets"]) {
3456
+ viewer["_nextspaceWidgets"] = {};
3457
+ }
3458
+ viewer["_nextspaceWidgets"][widgetId] = widget;
3459
+ }
3460
+ function unmarkViewerWithWidget(viewer, widgetId, widget) {
3461
+ if (viewer["_nextspaceWidgets"]) {
3462
+ delete viewer["_nextspaceWidgets"][widgetId];
3463
+ }
3464
+ }
3465
+
3466
+ var WidgetControlViewBar;
3467
+ (function (WidgetControlViewBar) {
3468
+ class AControl {
3469
+ get WidgetViewBar() {
3470
+ return this._widget;
3471
+ }
3472
+ get Container() {
3473
+ return this._container;
3474
+ }
3475
+ get Element() {
3476
+ return this._element;
3477
+ }
3478
+ get Disposed() {
3479
+ return this._disposed;
3480
+ }
3481
+ get Enabled() {
3482
+ return this._enabled;
3483
+ }
3484
+ constructor(params) {
3485
+ this._disposed = false;
3486
+ this._enabled = false;
3487
+ let { container, widget, element } = params;
3488
+ this._widget = widget;
3489
+ this._container = container;
3490
+ this._element = element;
3491
+ }
3492
+ Toggle() {
3493
+ }
3494
+ Dispose() {
3495
+ this._disposed = true;
3496
+ }
3497
+ }
3498
+ WidgetControlViewBar.AControl = AControl;
3499
+ })(WidgetControlViewBar || (WidgetControlViewBar = {}));
3500
+
3501
+ /**
3502
+ * The fullscreen control is a simple toggle.
3503
+ * There is no HTML element. However we do swap the icon based on the toggle state.
3504
+ */
3505
+ class WidgetControlViewBarFullscreen extends WidgetControlViewBar.AControl {
3506
+ constructor(params) {
3507
+ super(params);
3508
+ }
3509
+ Dispose() {
3510
+ super.Dispose();
3511
+ }
3512
+ Toggle() {
3513
+ if (this.Disposed) {
3514
+ return;
3515
+ }
3516
+ super.Toggle();
3517
+ // Toggle fullscreen.
3518
+ this._enabled = false;
3519
+ if (Fullscreen.enabled) {
3520
+ if (Fullscreen.fullscreen) {
3521
+ Fullscreen.exitFullscreen();
3522
+ }
3523
+ else {
3524
+ Fullscreen.requestFullscreen(document.body);
3525
+ this._enabled = true;
3526
+ }
3527
+ }
3528
+ }
3529
+ }
3530
+
3531
+ class WidgetControlViewBarSearch extends WidgetControlViewBar.AControl {
3532
+ constructor(params) {
3533
+ super(params);
3534
+ this.STYLESHEET_ID = "nextspace-control-view-bar-searchbar-stylesheet";
3535
+ this._generateStyles();
3536
+ this._generateElement();
3537
+ }
3538
+ Dispose() {
3539
+ super.Dispose();
3540
+ if (this._element && this._element.parentElement) {
3541
+ this._element.parentElement.removeChild(this._element);
3542
+ }
3543
+ if (this._results && this._results.parentElement) {
3544
+ this._results.parentElement.removeChild(this._results);
3545
+ }
3546
+ }
3547
+ Toggle() {
3548
+ if (this.Disposed) {
3549
+ return;
3550
+ }
3551
+ super.Toggle();
3552
+ this._enabled = !this._enabled;
3553
+ if (this._enabled) {
3554
+ this._display();
3555
+ }
3556
+ else {
3557
+ this._hide();
3558
+ }
3559
+ }
3560
+ _generateStyles() {
3561
+ if (document.getElementById(this.STYLESHEET_ID)) {
3562
+ return;
3563
+ }
3564
+ const style = document.createElement("style");
3565
+ style.id = this.STYLESHEET_ID;
3566
+ style.innerHTML = `
3567
+ .NextspaceSearchBar {
3568
+ display: flex;
3569
+ box-sizing: border-box;
3570
+ height: 100%;
3571
+ font-family: sans-serif;
3572
+ }
3573
+
3574
+ .NextspaceSearchBar * {
3575
+ box-sizing: border-box;
3576
+ }
3577
+
3578
+ .NextspaceSearchBar[is-opened="true"] .NextspaceSearchBarContent {
3579
+ display: flex;
2855
3580
  width: 260px;
2856
3581
  }
2857
3582
 
@@ -3502,1059 +4227,485 @@ class WidgetViewBar extends Widget.AWidget {
3502
4227
  break;
3503
4228
  default:
3504
4229
  if (this.customControls.has(control) === false) {
3505
- console.error(`Control ${control} not found.`);
3506
- return;
3507
- }
3508
- const clazz = this.customControls.get(control);
3509
- controller = new clazz({
3510
- widget: this,
3511
- container: this._row
3512
- });
3513
- break;
3514
- }
3515
- this.controls.set(control, controller);
3516
- }
3517
- /**
3518
- * Updates the panel styles based on the current state.
3519
- * Eg: if a control is enabled, the button should be highlighted.
3520
- */
3521
- _updatePanelStyles() {
3522
- const buttons = this._element.querySelectorAll(".NextspaceViewBarControl");
3523
- buttons.forEach((button) => {
3524
- const buttonTab = button.getAttribute("widget-view-bar-control");
3525
- const controller = this.controls.get(buttonTab);
3526
- const isCustomEnabledState = button.getAttribute("custom-enabled-state") === "true";
3527
- if (isCustomEnabledState) {
3528
- button.setAttribute("is-enabled", "false");
3529
- }
3530
- else {
3531
- button.setAttribute("is-enabled", (controller === null || controller === void 0 ? void 0 : controller.Enabled) ? "true" : "false");
3532
- }
3533
- });
3534
- }
3535
- }
3536
-
3537
- function isTurfAvailable() {
3538
- return window && window.turf != null;
3539
- }
3540
- /**
3541
- * Util for simplifying geometry on the fly.
3542
- */
3543
- var SimplifyGeometry;
3544
- (function (SimplifyGeometry) {
3545
- /**
3546
- * Returns the total number of points in the geometry.
3547
- * @param geometry
3548
- * @param limit number to count up to before returning.
3549
- * @returns
3550
- */
3551
- function CountPoints(geometry, limit) {
3552
- let count = 0;
3553
- const traverse = (geometry) => {
3554
- if (geometry.MultiGeometry) {
3555
- for (let i = 0; i < geometry.MultiGeometry.length; i++) {
3556
- traverse(geometry.MultiGeometry[i]);
3557
- // Reached the limit, return.
3558
- if (limit && count >= limit) {
3559
- return;
3560
- }
3561
- }
3562
- }
3563
- else if (geometry.Polygon) {
3564
- for (let i = 0; i < geometry.Polygon.length; i++) {
3565
- const polygon = geometry.Polygon[i];
3566
- count += Geometry$1.ParsePoints(polygon.LinearRing).length;
3567
- }
3568
- }
3569
- else if (geometry.LineString) {
3570
- count += Geometry$1.ParsePoints(geometry.LineString).length;
3571
- }
3572
- else if (geometry.Point) {
3573
- count += 1;
3574
- }
3575
- };
3576
- traverse(geometry);
3577
- return count;
3578
- }
3579
- SimplifyGeometry.CountPoints = CountPoints;
3580
- /**
3581
- * Simplifies input geometry.
3582
- * This will turn it into GeoJSON, run it through turf, then back to Bruce geometry.
3583
- * @param geometry
3584
- */
3585
- function Simplify(entityId, geometry, tolerance) {
3586
- var _a;
3587
- if (!geometry || !isTurfAvailable() || !turf.simplify) {
3588
- return geometry;
3589
- }
3590
- // Convert to geojson so that we can interact with turf.
3591
- const gFeature = Geometry$1.ToGeoJsonFeature({
3592
- geometry: geometry
3593
- });
3594
- // Unkink the geometry.
3595
- // This removes overlapping polygons before we start merging and simplifying.
3596
- // Commented out because it has crashes and doesn't handle holes.
3597
- untangleFeature(gFeature);
3598
- // Union the geometry.
3599
- // This merges overlapping polygons.
3600
- unionFeature(gFeature);
3601
- // Simplify the geometry.
3602
- if (tolerance > 0) {
3603
- gFeature.geometry = turf.simplify(gFeature.geometry, {
3604
- tolerance: tolerance,
3605
- highQuality: true,
3606
- mutate: true
3607
- });
3608
- }
3609
- // Converting back to Bruce geometry.
3610
- geometry = (_a = Geometry$1.FromGeoJson({
3611
- geoJson: gFeature
3612
- })) === null || _a === void 0 ? void 0 : _a.geometry;
3613
- return geometry;
3614
- }
3615
- SimplifyGeometry.Simplify = Simplify;
3616
- })(SimplifyGeometry || (SimplifyGeometry = {}));
3617
- /**
3618
- * Runs through all found polygons and runs unkink through turf on them.
3619
- * @param feature
3620
- */
3621
- function untangleFeature(feature) {
3622
- // Collection to add to because the result might be multiple from an unkink.
3623
- const collection = {
3624
- geometries: [],
3625
- type: "GeometryCollection"
3626
- };
3627
- // Runs a dedupe and unkink on the coordinates.
3628
- // Returns if the coordinates were added to the collection.
3629
- const processCoordinates = (coords) => {
3630
- try {
3631
- // Dedupe the coordinates to avoid issues with unkink.
3632
- coords = dedupeCoordinates(coords);
3633
- const outer = [];
3634
- let inner = [];
3635
- // We'll unkink each ring separately as this is killing the holes when it is done as a whole.
3636
- // So we'll do it separate then recombine.
3637
- for (let i = 0; i < coords.length; i++) {
3638
- const ring = coords[i];
3639
- const unkink = turf.unkinkPolygon({
3640
- type: "Polygon",
3641
- coordinates: [ring]
3642
- });
3643
- if (unkink.type == "FeatureCollection") {
3644
- let target = i == 0 ? outer : inner;
3645
- for (let j = 0; j < unkink.features.length; j++) {
3646
- const unkinked = unkink.features[j].geometry.coordinates;
3647
- if (unkinked.length > 0) {
3648
- target.push(unkinked[0]);
3649
- }
3650
- }
3651
- }
3652
- else {
3653
- console.error("Unexpected unkink result.", unkink);
3654
- }
3655
- }
3656
- // Recreate the rings and reapply to the collection.
3657
- if (outer.length > 0) {
3658
- const combinedCoords = [outer[0]];
3659
- for (let i = 0; i < inner.length; i++) {
3660
- combinedCoords.push(inner[i]);
3661
- }
3662
- // Add the combined coordinates to the collection
3663
- const polygon = {
3664
- type: "Polygon",
3665
- coordinates: combinedCoords
3666
- };
3667
- // Ensure right-hand rule is followed.
3668
- ensureRightHandRule(polygon);
3669
- // Add to the collection.
3670
- collection.geometries.push(polygon);
3671
- return true;
3672
- }
3673
- }
3674
- catch (e) {
3675
- // console.error("Failed to unkink polygon.", e);
3676
- }
3677
- return false;
3678
- };
3679
- const processGeometry = (geometry) => {
3680
- let added = false;
3681
- if (geometry.type == "Polygon") {
3682
- added = processCoordinates(geometry.coordinates);
3683
- }
3684
- else if (geometry.type == "MultiPolygon") {
3685
- for (let i = 0; i < geometry.coordinates.length; i++) {
3686
- added = processCoordinates(geometry.coordinates[i]) || added;
3687
- }
3688
- }
3689
- if (!added) {
3690
- // Adding original since we can't unkink it.
3691
- collection.geometries.push(geometry);
3692
- }
3693
- };
3694
- if (feature.geometry.type == "GeometryCollection") {
3695
- feature.geometry.geometries.forEach((geometry) => {
3696
- processGeometry(geometry);
3697
- });
3698
- }
3699
- else {
3700
- processGeometry(feature.geometry);
3701
- }
3702
- // Re-assign the geometry.
3703
- if (collection.geometries.length == 1) {
3704
- feature.geometry = collection.geometries[0];
3705
- }
3706
- else {
3707
- feature.geometry = collection;
3708
- }
3709
- }
3710
- /**
3711
- * Runs through all found polygons and unions them using turf.
3712
- * Failed unions are ignored and the original is kept.
3713
- * @param feature
3714
- */
3715
- function unionFeature(feature) {
3716
- // Collection to add to because the result might be multiple from an unkink.
3717
- const collection = {
3718
- geometries: [],
3719
- type: "GeometryCollection"
3720
- };
3721
- // We'll turn each geometry into a feature and union them.
3722
- const tmpCollection = {
3723
- features: [],
3724
- type: "FeatureCollection"
3725
- };
3726
- if (feature.geometry.type == "GeometryCollection") {
3727
- feature.geometry.geometries.forEach((geometry) => {
3728
- if (geometry.type == "Polygon") {
3729
- tmpCollection.features.push({
3730
- type: "Feature",
3731
- geometry: geometry,
3732
- properties: {}
3733
- });
3734
- }
3735
- else if (geometry.type == "MultiPolygon") {
3736
- for (let i = 0; i < geometry.coordinates.length; i++) {
3737
- tmpCollection.features.push({
3738
- type: "Feature",
3739
- geometry: {
3740
- type: "Polygon",
3741
- coordinates: geometry.coordinates[i]
3742
- },
3743
- properties: {}
3744
- });
3745
- }
3746
- }
3747
- // Only focusing on polygons.
3748
- else {
3749
- collection.geometries.push(geometry);
3750
- }
3751
- });
3752
- }
3753
- else if (feature.geometry.type == "Polygon") {
3754
- tmpCollection.features.push({
3755
- type: "Feature",
3756
- geometry: feature.geometry,
3757
- properties: {}
3758
- });
3759
- }
3760
- else if (feature.geometry.type == "MultiPolygon") {
3761
- for (let i = 0; i < feature.geometry.coordinates.length; i++) {
3762
- tmpCollection.features.push({
3763
- type: "Feature",
3764
- geometry: {
3765
- type: "Polygon",
3766
- coordinates: feature.geometry.coordinates[i]
3767
- },
3768
- properties: {}
3769
- });
3770
- }
3771
- }
3772
- // No polygons to union.
3773
- // Need at least 2 to union.
3774
- if (tmpCollection.features.length < 2) {
3775
- return;
3776
- }
3777
- // Now we'll union them.
3778
- try {
3779
- const union = turf.union(tmpCollection);
3780
- if (union.geometry.type == "Polygon") {
3781
- collection.geometries.push(union.geometry);
3782
- }
3783
- else if (union.geometry.type == "MultiPolygon") {
3784
- for (let i = 0; i < union.geometry.coordinates.length; i++) {
3785
- collection.geometries.push({
3786
- type: "Polygon",
3787
- coordinates: union.geometry.coordinates[i]
3788
- });
3789
- }
3790
- }
3791
- else {
3792
- // Returning early because the result is unexpected.
3793
- return;
3794
- }
3795
- }
3796
- catch (e) {
3797
- // console.error("Failed to union polygons.", e);
3798
- return;
3799
- }
3800
- // Re-assign the geometry.
3801
- if (collection.geometries.length == 1) {
3802
- feature.geometry = collection.geometries[0];
3803
- }
3804
- else {
3805
- feature.geometry = collection;
3806
- }
3807
- }
3808
- function dedupeCoordinates(inputCoords) {
3809
- return inputCoords.map(ring => {
3810
- if (ring.length < 2) {
3811
- return ring;
3812
- }
3813
- const dedupeCoords = [];
3814
- const uniqueCoords = new Set();
3815
- // Dedupe the points.
3816
- ring.forEach(coord => {
3817
- const key = coord.join(',');
3818
- if (!uniqueCoords.has(key)) {
3819
- uniqueCoords.add(key);
3820
- dedupeCoords.push(coord);
3821
- }
3822
- });
3823
- // Make sure the last point matches the first.
3824
- if (dedupeCoords.length > 1) {
3825
- if (dedupeCoords[0][0] != dedupeCoords[dedupeCoords.length - 1][0] ||
3826
- dedupeCoords[0][1] != dedupeCoords[dedupeCoords.length - 1][1]) {
3827
- dedupeCoords.push(dedupeCoords[0]);
3828
- }
3829
- }
3830
- return dedupeCoords;
3831
- });
3832
- }
3833
- function ensureRightHandRule(polygon) {
3834
- // Ensure the outer ring follows the right-hand rule
3835
- if (polygon.coordinates.length > 0) {
3836
- const outerRing = polygon.coordinates[0];
3837
- if (isClockwise(outerRing)) {
3838
- polygon.coordinates[0] = outerRing.reverse();
3839
- }
3840
- }
3841
- // Ensure any inner rings (holes) follow the right-hand rule
3842
- for (let i = 1; i < polygon.coordinates.length; i++) {
3843
- const innerRing = polygon.coordinates[i];
3844
- if (!isClockwise(innerRing)) {
3845
- polygon.coordinates[i] = innerRing.reverse();
3846
- }
3847
- }
3848
- }
3849
- function isClockwise(ring) {
3850
- let sum = 0;
3851
- for (let i = 0; i < ring.length - 1; i++) {
3852
- const p1 = ring[i];
3853
- const p2 = ring[i + 1];
3854
- sum += (p2[0] - p1[0]) * (p2[1] + p1[1]);
3855
- }
3856
- return sum > 0;
3857
- }
3858
-
3859
- function OnNextCRender(viewer, callback) {
3860
- const removal = viewer.scene.postRender.addEventListener(() => {
3861
- removal();
3862
- callback();
3863
- });
3864
- }
3865
- function GetCValue(viewer, obj) {
3866
- if (obj === null || obj === void 0 ? void 0 : obj.getValue) {
3867
- let date = viewer.scene.lastRenderTime;
3868
- if (!date) {
3869
- date = viewer.clock.currentTime;
3870
- }
3871
- return obj.getValue(date);
3872
- }
3873
- return obj;
3874
- }
3875
- /*
3876
- * Marks an EntityCollection as one this library created and fully controls (a menu item's own data source).
3877
- */
3878
- const OWNED_CCOLLECTION_KEY = "_bruceOwnedCollection";
3879
- function MarkCCollectionOwned(collection) {
3880
- if (collection) {
3881
- collection[OWNED_CCOLLECTION_KEY] = true;
3882
- }
3883
- }
3884
- function IsCCollectionOwned(collection) {
3885
- return Boolean(collection && collection[OWNED_CCOLLECTION_KEY]);
3886
- }
3887
- /**
3888
- * Runs a bulk collection mutation with every given collection's events suspended, so Cesium raises one
3889
- * collectionChanged per collection for the whole pass instead of one per entity.
3890
- *
3891
- * Takes a set of collections rather than assuming `viewer.entities`, because managed visuals live in their menu
3892
- * item's own data source: suspending the wrong collection silently does nothing.
3893
- * @param collections Duplicates and empty entries are ignored.
3894
- * @param run
3895
- */
3896
- function WithSuspendedCCollections(collections, run) {
3897
- const unique = [];
3898
- for (const collection of collections) {
3899
- if (collection && unique.indexOf(collection) === -1) {
3900
- unique.push(collection);
3901
- }
3902
- }
3903
- for (const collection of unique) {
3904
- collection.suspendEvents();
3905
- }
3906
- try {
3907
- return run();
3908
- }
3909
- finally {
3910
- for (const collection of unique) {
3911
- try {
3912
- collection.resumeEvents();
3913
- }
3914
- catch (e) {
3915
- console.error(e);
3916
- }
3917
- }
3918
- }
3919
- }
3920
- /**
3921
- * Returns the collection a graphic belongs to, falling back to the viewer's own when it has never been added.
3922
- * @param viewer
3923
- * @param entity
3924
- */
3925
- function GetCEntityCollection(viewer, entity) {
3926
- const owner = entity === null || entity === void 0 ? void 0 : entity.entityCollection;
3927
- return owner ? owner : viewer === null || viewer === void 0 ? void 0 : viewer.entities;
3928
- }
3929
- /**
3930
- * Returns whether a graphic is currently in the scene, looking in whichever collection owns it.
3931
- * @param viewer
3932
- * @param entity
3933
- */
3934
- function IsCEntityInScene(viewer, entity) {
3935
- const collection = GetCEntityCollection(viewer, entity);
3936
- return Boolean(collection && entity && collection.contains(entity));
3937
- }
3938
- /**
3939
- * Removes a graphic from whichever collection owns it. Returns whether it removed anything.
3940
- * @param viewer
3941
- * @param entity
3942
- */
3943
- function RemoveCEntityFromScene(viewer, entity) {
3944
- var _a;
3945
- if (!entity) {
3946
- return false;
3947
- }
3948
- const collection = GetCEntityCollection(viewer, entity);
3949
- if (collection === null || collection === void 0 ? void 0 : collection.contains(entity)) {
3950
- return collection.remove(entity);
3951
- }
3952
- // A stale owner reference and the graphic ended up in the viewer's collection anyway.
3953
- if (collection !== (viewer === null || viewer === void 0 ? void 0 : viewer.entities) && ((_a = viewer === null || viewer === void 0 ? void 0 : viewer.entities) === null || _a === void 0 ? void 0 : _a.contains(entity))) {
3954
- return viewer.entities.remove(entity);
3955
- }
3956
- return false;
3957
- }
3958
- /**
3959
- * Adds a graphic back into whichever collection owns it, or the viewer's if it has no owner yet.
3960
- * @param viewer
3961
- * @param entity
3962
- */
3963
- function AddCEntityToScene(viewer, entity, fallbackCollection) {
3964
- if (!entity) {
3965
- return false;
3966
- }
3967
- // An existing owner always wins, so a graphic is never migrated out from under whoever holds it.
3968
- const owner = entity.entityCollection;
3969
- const collection = owner ? owner : (fallbackCollection ? fallbackCollection : viewer === null || viewer === void 0 ? void 0 : viewer.entities);
3970
- if (!collection || collection.contains(entity)) {
3971
- return false;
3972
- }
3973
- collection.add(entity);
3974
- return true;
3975
- }
3976
- /**
3977
- * Returns whether toggling `show` on these graphics is safe, rather than having to add/remove them from the
3978
- * entity collection to hide them.
3979
- *
3980
- * Toggling show is far cheaper than re-adding the graphic to the viewer however a Cesium bug means we can't always use it.
3981
- * See: https://github.com/CesiumGS/cesium/issues/9370
3982
- * @param parts The graphic and any sibling graphics, eg. from EntityUtils.GatherEntity.
3983
- */
3984
- function CanToggleShowSafely(parts) {
3985
- if (!(parts === null || parts === void 0 ? void 0 : parts.length)) {
3986
- return false;
3987
- }
3988
- for (const part of parts) {
3989
- if (!(part instanceof Entity)) {
3990
- // Not an Entity, so not something whose `show` we can drive.
3991
- return false;
3992
- }
3993
- if (part.polyline && isTruthyCValue(part.polyline.clampToGround)) {
3994
- return false;
3995
- }
3996
- const materialGraphics = [part.polygon, part.corridor, part.ellipse, part.rectangle, part.wall, part.polylineVolume];
3997
- for (const graphic of materialGraphics) {
3998
- if (graphic && !isPlainColorMaterial(graphic.material)) {
3999
- return false;
4000
- }
4001
- }
4002
- }
4003
- return true;
4004
- }
4005
- /**
4006
- * Returns whether a material is a plain colour, which is what keeps a graphic out of Cesium's per-material batches.
4007
- * Anything unrecognised counts as not plain, so callers stay on the conservative side.
4008
- * @param material
4009
- */
4010
- function isPlainColorMaterial(material) {
4011
- if (material == null) {
4012
- // Cesium defaults an absent material to white, a plain colour.
4013
- return true;
4014
- }
4015
- return material instanceof ColorMaterialProperty || material instanceof Color;
4016
- }
4017
- /**
4018
- * Resolves a possibly-property boolean without needing a viewer clock, treating anything undeterminable as true
4019
- * so callers stay on the conservative side.
4020
- * @param value
4021
- */
4022
- function isTruthyCValue(value) {
4023
- if (value == null) {
4024
- return false;
4025
- }
4026
- if (typeof value.getValue === "function") {
4027
- if (value instanceof ConstantProperty) {
4028
- return Boolean(value.valueOf());
4029
- }
4030
- // A non-constant property could be true at any moment, so assume it is.
4031
- return true;
4032
- }
4033
- return Boolean(value);
4034
- }
4035
- /**
4036
- * Returns if two resolved Cesium property values are equal, using the value's own equals() when it has one.
4037
- * @param a
4038
- * @param b
4039
- */
4040
- function AreCValuesEqual(a, b) {
4041
- if (a === b) {
4042
- return true;
4043
- }
4044
- // One side is null/undefined and the other isn't.
4045
- if (a == null || b == null) {
4046
- return false;
4047
- }
4048
- if (typeof a.equals === "function") {
4049
- return a.equals(b) === true;
4050
- }
4051
- return false;
4052
- }
4053
- /**
4054
- * Wraps a value in a ConstantProperty and assigns it to a graphic's property, but only when the resolved
4055
- * value actually differs. Returns whether it assigned.
4056
- * @param params
4057
- */
4058
- function SetCPropIfChanged(params) {
4059
- const { viewer, graphic, property, value, compare } = params;
4060
- if (!graphic) {
4061
- return false;
4062
- }
4063
- const oldValue = GetCValue(viewer, graphic[property]);
4064
- const isEqual = compare ? compare(oldValue, value) : AreCValuesEqual(oldValue, value);
4065
- if (isEqual) {
4066
- return false;
4067
- }
4068
- graphic[property] = new ConstantProperty(value);
4069
- return true;
4070
- }
4071
- function ColorToCColor(color) {
4072
- return new Color(color.red ? color.red / 255 : 0, color.green ? color.green / 255 : 0, color.blue ? color.blue / 255 : 0, color.alpha);
4073
- }
4074
- /**
4075
- * Removes duplicate points in a row and returns a new array.
4076
- * Passed array is not mutated.
4077
- * @param posses
4078
- */
4079
- function CullDuplicateCPosses(posses) {
4080
- const newPosses = [];
4081
- let lastPos = null;
4082
- for (let i = 0; i < posses.length; i++) {
4083
- const pos = posses[i];
4084
- // Avoiding 'Cesium.Cartesian3.equals' because passed data might be just a json blob in certain cases.
4085
- if (pos && (!lastPos || (pos.x != lastPos.x || pos.y != lastPos.y || pos.z != lastPos.z))) {
4086
- newPosses.push(pos);
4087
- lastPos = pos;
4088
- }
4089
- }
4090
- return newPosses;
4091
- }
4092
- /**
4093
- * Returns if the given positions are equal.
4094
- * @param a
4095
- * @param b
4096
- */
4097
- function CompareCPosses(a, b) {
4098
- // Same reference.
4099
- if (a == b) {
4100
- return true;
4101
- }
4102
- // Different lengths or one is null.
4103
- if ((!a || !b) || (a.length != b.length)) {
4104
- return false;
4105
- }
4106
- for (let i = 0; i < a.length; i++) {
4107
- const posA = a[i];
4108
- const posB = b[i];
4109
- // Null detected.
4110
- if (!posA || !posB) {
4111
- return false;
4112
- }
4113
- // Position values don't match.
4114
- if (!Cartes.IsEqualCartes3(posA, posB)) {
4115
- return false;
4116
- }
4117
- }
4118
- return true;
4119
- }
4120
- /**
4121
- * Returns if the given polygon hierarchies are equal.
4122
- * @param a
4123
- * @param b
4124
- */
4125
- function CompareCPolygonHierarchies(a, b) {
4126
- // Same reference.
4127
- if (a == b) {
4128
- return true;
4129
- }
4130
- // Different lengths or one is null.
4131
- if ((!a || !b) || (a.positions.length != b.positions.length)) {
4132
- return false;
4133
- }
4134
- // Positions don't match.
4135
- if (!CompareCPosses(a.positions, b.positions)) {
4136
- return false;
4137
- }
4138
- const holes = a.holes;
4139
- const bHoles = b.holes;
4140
- // Number of holes don't match.
4141
- if (holes.length != bHoles.length) {
4142
- return false;
4143
- }
4144
- for (let i = 0; i < holes.length; i++) {
4145
- // Hole positions don't match.
4146
- if (!CompareCPosses(holes[i].positions, bHoles[i].positions)) {
4147
- return false;
4148
- }
4149
- }
4150
- return true;
4151
- }
4152
-
4153
- const CESIUM_INSPECTOR_KEY = "_nextspace_inspector";
4154
- const CESIUM_TIMELINE_KEY = "_nextspace_timeline";
4155
- const CESIUM_TIMELINE_LIVE_KEY = "_nextspace_timeline_live";
4156
- const CESIUM_TIMELINE_LIVE_PADDING_KEY = "_nextspace_timeline_live_padding";
4157
- const CESIUM_TIMELINE_INTERVAL_KEY = "_nextspace_timeline_interval";
4158
- const CESIUM_MODEL_SPACE_KEY = "_nextspace_model_space";
4159
- const DEFAULT_LIVE_PADDING_SECONDS = 30 * 60;
4160
- var ViewUtils;
4161
- (function (ViewUtils) {
4162
- function GatherLegacyMapTiles(params) {
4163
- const viewer = params.viewer;
4164
- const collection = viewer.imageryLayers;
4165
- const tiles = [];
4166
- for (let i = 0; i < collection.length; i++) {
4167
- const layer = collection.get(i);
4168
- if (layer._bName) {
4169
- tiles.push({
4170
- alpha: layer.alpha,
4171
- brightness: layer.brightness,
4172
- contrast: layer.contrast,
4173
- hue: layer.hue,
4174
- saturation: layer.saturation,
4175
- gamma: layer.gamma,
4176
- title: layer._bName,
4177
- });
4178
- }
4179
- }
4180
- return {
4181
- imagery: tiles.reverse()
4182
- };
4183
- }
4184
- ViewUtils.GatherLegacyMapTiles = GatherLegacyMapTiles;
4185
- function GatherLegacyTerrainTile(params) {
4186
- const viewer = params.viewer;
4187
- const enabled = viewer.terrainProvider;
4188
- if (enabled === null || enabled === void 0 ? void 0 : enabled._bName) {
4189
- return {
4190
- terrain: enabled._bName
4191
- };
4192
- }
4193
- return {
4194
- terrain: "flatterrain"
4195
- };
4196
- }
4197
- ViewUtils.GatherLegacyTerrainTile = GatherLegacyTerrainTile;
4198
- function GatherMapTiles(params) {
4199
- const viewer = params.viewer;
4200
- const imagery = viewer.imageryLayers;
4201
- const tiles = [];
4202
- for (let i = 0; i < imagery.length; i++) {
4203
- const provider = imagery.get(i);
4204
- if (provider._bMeta) {
4205
- const idCombo = provider._bMeta.accountId + provider._bMeta.tilesetId;
4206
- if (!tiles.find(x => x.accountId + x.tilesetId === idCombo)) {
4207
- tiles.push({
4208
- accountId: provider._bMeta.accountId,
4209
- tilesetId: provider._bMeta.tilesetId,
4210
- alpha: provider.alpha,
4211
- brightness: provider.brightness,
4212
- contrast: provider.contrast,
4213
- hue: provider.hue,
4214
- saturation: provider.saturation,
4215
- gamma: provider.gamma
4216
- });
4217
- }
4218
- }
4219
- }
4220
- return {
4221
- imagery: tiles
4222
- };
4223
- }
4224
- ViewUtils.GatherMapTiles = GatherMapTiles;
4225
- function GatherTerrainTile(params) {
4226
- const viewer = params.viewer;
4227
- const provider = viewer.terrainProvider;
4228
- if (provider === null || provider === void 0 ? void 0 : provider._bMeta) {
4229
- return {
4230
- terrain: {
4231
- accountId: provider._bMeta.accountId,
4232
- tilesetId: provider._bMeta.tilesetId,
4233
- }
4234
- };
4235
- }
4236
- else if (provider instanceof EllipsoidTerrainProvider) {
4237
- return {
4238
- terrain: {
4239
- tilesetId: ProjectViewTile.EDefaultTerrain.FlatTerrain,
4240
- accountId: null
4241
- }
4242
- };
4243
- }
4244
- return null;
4245
- }
4246
- ViewUtils.GatherTerrainTile = GatherTerrainTile;
4247
- function SetTerrainWireframeStatus(params) {
4248
- if (!params.viewer[CESIUM_INSPECTOR_KEY]) {
4249
- const InspectorClass = CesiumInspector;
4250
- if (InspectorClass) {
4251
- const inspector = new InspectorClass(document.createElement("div"), params.viewer.scene);
4252
- inspector.container.style.display = "none";
4253
- params.viewer[CESIUM_INSPECTOR_KEY] = inspector;
4254
- params.viewer.scene.requestRender();
4255
- }
4256
- }
4257
- if (params.viewer[CESIUM_INSPECTOR_KEY]) {
4258
- params.viewer[CESIUM_INSPECTOR_KEY].viewModel.wireframe = params.status;
4259
- }
4260
- }
4261
- ViewUtils.SetTerrainWireframeStatus = SetTerrainWireframeStatus;
4262
- function GetTerrainWireframeStatus(params) {
4263
- var _a, _b;
4264
- if (!params.viewer[CESIUM_INSPECTOR_KEY]) {
4265
- return false;
4266
- }
4267
- return (_b = (_a = params.viewer[CESIUM_INSPECTOR_KEY]) === null || _a === void 0 ? void 0 : _a.viewModel) === null || _b === void 0 ? void 0 : _b.wireframe;
4268
- }
4269
- ViewUtils.GetTerrainWireframeStatus = GetTerrainWireframeStatus;
4270
- /**
4271
- * Changes between perspective and orthographic view.
4272
- * When Cesium stops being bad at picking positions in 2d mode we'll use the flat earth mode instead.
4273
- * @param params
4274
- */
4275
- function Set2dStatus(params) {
4276
- const { viewer, status: is2d, moveCamera } = params;
4277
- const curLens2d = viewer.camera.frustum instanceof OrthographicFrustum;
4278
- if (curLens2d && !is2d) {
4279
- OnNextCRender(viewer, () => {
4280
- viewer.camera.switchToPerspectiveFrustum();
4281
- viewer.scene.screenSpaceCameraController.enableTilt = true;
4282
- });
4283
- viewer.scene.requestRender();
4284
- }
4285
- else if (!curLens2d && is2d) {
4286
- OnNextCRender(viewer, () => {
4287
- viewer.camera.switchToOrthographicFrustum();
4288
- viewer.scene.screenSpaceCameraController.enableTilt = false;
4289
- });
4290
- if (moveCamera != false) {
4291
- try {
4292
- // Face camera downwards to make it look 2d.
4293
- // We want to try make it look at the center-point of the current view.
4294
- // If center cannot be calculated then we'll simply raise the camera and face it downwards.
4295
- const scene = viewer.scene;
4296
- const windowPosition = new Cartesian2(scene.canvas.clientWidth / 2, scene.canvas.clientHeight / 2);
4297
- const ray = viewer.camera.getPickRay(windowPosition);
4298
- const intersection = scene.globe.pick(ray, scene);
4299
- let center;
4300
- if (defined(intersection)) {
4301
- center = Cartographic.fromCartesian(intersection);
4302
- }
4303
- // Use current camera position if we can't calculate the center.
4304
- else {
4305
- center = Cartographic.fromCartesian(viewer.camera.position);
4306
- center.height = 0;
4307
- }
4308
- center.height = viewer.camera.positionCartographic.height + 100;
4309
- viewer.camera.setView({
4310
- destination: Cartographic.toCartesian(center),
4311
- orientation: {
4312
- heading: 0.0,
4313
- pitch: Math$1.toRadians(-90.0),
4314
- roll: 0.0
4315
- }
4316
- });
4317
- }
4318
- catch (e) {
4319
- console.error(e);
4320
- }
4321
- }
4322
- viewer.scene.requestRender();
4323
- }
4324
- }
4325
- ViewUtils.Set2dStatus = Set2dStatus;
4326
- function Get2dStatus(params) {
4327
- const { viewer } = params;
4328
- return viewer.camera.frustum instanceof OrthographicFrustum;
4329
- }
4330
- ViewUtils.Get2dStatus = Get2dStatus;
4331
- function SetLockedCameraStatus(params) {
4332
- const { viewer, status } = params;
4333
- const scene = viewer === null || viewer === void 0 ? void 0 : viewer.scene;
4334
- if (!scene) {
4335
- return;
4336
- }
4337
- if (status) {
4338
- scene.screenSpaceCameraController.enableInputs = false;
4339
- scene.screenSpaceCameraController.enableTranslate = false;
4340
- scene.screenSpaceCameraController.enableZoom = false;
4341
- scene.screenSpaceCameraController.enableRotate = false;
4342
- scene.screenSpaceCameraController.enableTilt = false;
4343
- }
4344
- else {
4345
- scene.screenSpaceCameraController.enableInputs = true;
4346
- scene.screenSpaceCameraController.enableTranslate = true;
4347
- scene.screenSpaceCameraController.enableZoom = true;
4348
- scene.screenSpaceCameraController.enableRotate = true;
4349
- if (!ViewUtils.Get2dStatus({ viewer })) {
4350
- scene.screenSpaceCameraController.enableTilt = true;
4351
- }
4230
+ console.error(`Control ${control} not found.`);
4231
+ return;
4232
+ }
4233
+ const clazz = this.customControls.get(control);
4234
+ controller = new clazz({
4235
+ widget: this,
4236
+ container: this._row
4237
+ });
4238
+ break;
4352
4239
  }
4353
- viewer.scene.requestRender();
4240
+ this.controls.set(control, controller);
4354
4241
  }
4355
- ViewUtils.SetLockedCameraStatus = SetLockedCameraStatus;
4356
- function GetLockedCameraStatus(params) {
4357
- var _a;
4358
- const scene = (_a = params.viewer) === null || _a === void 0 ? void 0 : _a.scene;
4359
- if (!scene) {
4360
- return false;
4361
- }
4362
- return !scene.screenSpaceCameraController.enableTranslate;
4242
+ /**
4243
+ * Updates the panel styles based on the current state.
4244
+ * Eg: if a control is enabled, the button should be highlighted.
4245
+ */
4246
+ _updatePanelStyles() {
4247
+ const buttons = this._element.querySelectorAll(".NextspaceViewBarControl");
4248
+ buttons.forEach((button) => {
4249
+ const buttonTab = button.getAttribute("widget-view-bar-control");
4250
+ const controller = this.controls.get(buttonTab);
4251
+ const isCustomEnabledState = button.getAttribute("custom-enabled-state") === "true";
4252
+ if (isCustomEnabledState) {
4253
+ button.setAttribute("is-enabled", "false");
4254
+ }
4255
+ else {
4256
+ button.setAttribute("is-enabled", (controller === null || controller === void 0 ? void 0 : controller.Enabled) ? "true" : "false");
4257
+ }
4258
+ });
4363
4259
  }
4364
- ViewUtils.GetLockedCameraStatus = GetLockedCameraStatus;
4260
+ }
4261
+
4262
+ function isTurfAvailable() {
4263
+ return window && window.turf != null;
4264
+ }
4265
+ /**
4266
+ * Util for simplifying geometry on the fly.
4267
+ */
4268
+ var SimplifyGeometry;
4269
+ (function (SimplifyGeometry) {
4365
4270
  /**
4366
- * Returns the current camera time and related settings.
4367
- * @param params
4271
+ * Returns the total number of points in the geometry.
4272
+ * @param geometry
4273
+ * @param limit number to count up to before returning.
4368
4274
  * @returns
4369
4275
  */
4370
- function GetTimeDetails(params) {
4371
- const { viewer } = params;
4372
- const clock = viewer.clock;
4373
- return {
4374
- animationSpeed: clock.multiplier,
4375
- isAnimating: clock.shouldAnimate,
4376
- startTime: clock.startTime,
4377
- startTimeIso: clock.startTime.toString(),
4378
- currentTime: clock.currentTime,
4379
- currentTimeIso: clock.currentTime.toString(),
4380
- stopTime: clock.stopTime,
4381
- stopTimeIso: clock.stopTime.toString(),
4382
- areCesiumValues: clock[CESIUM_TIMELINE_KEY] != true,
4383
- isLive: clock[CESIUM_TIMELINE_LIVE_KEY] == true,
4384
- livePaddingSeconds: clock[CESIUM_TIMELINE_LIVE_PADDING_KEY] || DEFAULT_LIVE_PADDING_SECONDS
4276
+ function CountPoints(geometry, limit) {
4277
+ let count = 0;
4278
+ const traverse = (geometry) => {
4279
+ if (geometry.MultiGeometry) {
4280
+ for (let i = 0; i < geometry.MultiGeometry.length; i++) {
4281
+ traverse(geometry.MultiGeometry[i]);
4282
+ // Reached the limit, return.
4283
+ if (limit && count >= limit) {
4284
+ return;
4285
+ }
4286
+ }
4287
+ }
4288
+ else if (geometry.Polygon) {
4289
+ for (let i = 0; i < geometry.Polygon.length; i++) {
4290
+ const polygon = geometry.Polygon[i];
4291
+ count += Geometry$1.ParsePoints(polygon.LinearRing).length;
4292
+ }
4293
+ }
4294
+ else if (geometry.LineString) {
4295
+ count += Geometry$1.ParsePoints(geometry.LineString).length;
4296
+ }
4297
+ else if (geometry.Point) {
4298
+ count += 1;
4299
+ }
4385
4300
  };
4301
+ traverse(geometry);
4302
+ return count;
4386
4303
  }
4387
- ViewUtils.GetTimeDetails = GetTimeDetails;
4304
+ SimplifyGeometry.CountPoints = CountPoints;
4388
4305
  /**
4389
- * Sets the Cesium clock values.
4390
- * If a value is not provided, then 'areCesiumValues' checked to see if the values are Cesium values.
4391
- * If they're currently Cesium set values then our defaults are used.
4392
- * @param params
4306
+ * Simplifies input geometry.
4307
+ * This will turn it into GeoJSON, run it through turf, then back to Bruce geometry.
4308
+ * @param geometry
4393
4309
  */
4394
- function SetTimeDetails(params) {
4395
- let { viewer, animationSpeed, isAnimating, startTime, currentTime, stopTime, startTimeIso, stopTimeIso, currentTimeIso, isLive, livePaddingSeconds } = params;
4396
- const clock = viewer.clock;
4397
- if (startTime) {
4398
- clock.startTime = startTime;
4310
+ function Simplify(entityId, geometry, tolerance) {
4311
+ var _a;
4312
+ if (!geometry || !isTurfAvailable() || !turf.simplify) {
4313
+ return geometry;
4399
4314
  }
4400
- else if (startTimeIso) {
4401
- const startDate = JulianDate.fromIso8601(startTimeIso);
4402
- if (startDate) {
4403
- clock.startTime = startDate;
4404
- }
4315
+ const original = geometry;
4316
+ // Convert to geojson so that we can interact with turf.
4317
+ const gFeature = Geometry$1.ToGeoJsonFeature({
4318
+ geometry: geometry
4319
+ });
4320
+ // Unkink the geometry.
4321
+ // This removes overlapping polygons before we start merging and simplifying.
4322
+ // Commented out because it has crashes and doesn't handle holes.
4323
+ untangleFeature(gFeature);
4324
+ // Union the geometry.
4325
+ // This merges overlapping polygons.
4326
+ unionFeature(gFeature);
4327
+ // Simplify the geometry.
4328
+ if (tolerance > 0) {
4329
+ gFeature.geometry = turf.simplify(gFeature.geometry, {
4330
+ tolerance: tolerance,
4331
+ highQuality: true,
4332
+ mutate: true
4333
+ });
4405
4334
  }
4406
- if (currentTime) {
4407
- clock.currentTime = currentTime;
4335
+ // Converting back to Bruce geometry.
4336
+ const simplified = (_a = Geometry$1.FromGeoJson({
4337
+ geoJson: gFeature
4338
+ })) === null || _a === void 0 ? void 0 : _a.geometry;
4339
+ // A polygon we cannot vouch for is worse than an unsimplified one, so fall back instead of shipping it.
4340
+ if (!simplified || !isSafeToRender(simplified)) {
4341
+ return original;
4408
4342
  }
4409
- else if (currentTimeIso) {
4410
- const currentDate = JulianDate.fromIso8601(currentTimeIso);
4411
- if (currentDate) {
4412
- clock.currentTime = currentDate;
4413
- }
4343
+ return simplified;
4344
+ }
4345
+ SimplifyGeometry.Simplify = Simplify;
4346
+ /**
4347
+ * Whether a simplified geometry still describes something a renderer can triangulate.
4348
+ * @param geometry the simplification result.
4349
+ * @returns false when any polygon has a collapsed ring, a hole outside its outer ring, or a hole
4350
+ * wound the same way as its outer ring.
4351
+ */
4352
+ function IsSafeToRender(geometry) {
4353
+ return isSafeToRender(geometry);
4354
+ }
4355
+ SimplifyGeometry.IsSafeToRender = IsSafeToRender;
4356
+ })(SimplifyGeometry || (SimplifyGeometry = {}));
4357
+ // A ring needs three distinct corners plus the closing repeat before it encloses any area.
4358
+ const MIN_RING_POSITIONS = 4;
4359
+ function isSafeToRender(geometry) {
4360
+ let safe = true;
4361
+ const check = (g) => {
4362
+ if (!safe) {
4363
+ return;
4414
4364
  }
4415
- if (stopTime) {
4416
- clock.stopTime = stopTime;
4365
+ if (g === null || g === void 0 ? void 0 : g.MultiGeometry) {
4366
+ g.MultiGeometry.forEach(check);
4367
+ return;
4417
4368
  }
4418
- else if (stopTimeIso) {
4419
- const stopDate = JulianDate.fromIso8601(stopTimeIso);
4420
- if (stopDate) {
4421
- clock.stopTime = stopDate;
4422
- }
4369
+ if (!(g === null || g === void 0 ? void 0 : g.Polygon) || g.Polygon.length === 0) {
4370
+ return;
4423
4371
  }
4424
- clock.clockRange = ClockRange.LOOP_STOP;
4425
- const areCesiumValues = clock[CESIUM_TIMELINE_KEY] != true;
4426
- if (areCesiumValues) {
4427
- if (isNaN(animationSpeed) || animationSpeed == null) {
4428
- animationSpeed = 1;
4372
+ let outer = null;
4373
+ let outerIsClockwise = false;
4374
+ for (let i = 0; i < g.Polygon.length; i++) {
4375
+ const points = Geometry$1.ParsePoints(g.Polygon[i].LinearRing);
4376
+ if (!points || points.length < MIN_RING_POSITIONS) {
4377
+ safe = false;
4378
+ return;
4429
4379
  }
4430
- if (isAnimating == null) {
4431
- isAnimating = false;
4380
+ const clockwise = signedRingArea(points) < 0;
4381
+ if (g.Polygon[i].Facing !== "in") {
4382
+ outer = points;
4383
+ outerIsClockwise = clockwise;
4384
+ continue;
4432
4385
  }
4433
- if (isLive == null) {
4434
- isLive = false;
4386
+ // A hole with no outer ring ahead of it cannot be subtracted from anything.
4387
+ if (!outer) {
4388
+ safe = false;
4389
+ return;
4435
4390
  }
4436
- if (livePaddingSeconds == null) {
4437
- livePaddingSeconds = DEFAULT_LIVE_PADDING_SECONDS;
4391
+ if (clockwise === outerIsClockwise) {
4392
+ safe = false;
4393
+ return;
4394
+ }
4395
+ for (let j = 0; j < points.length; j++) {
4396
+ if (!isPointInRing(points[j], outer)) {
4397
+ safe = false;
4398
+ return;
4399
+ }
4438
4400
  }
4439
4401
  }
4440
- if (!isNaN(animationSpeed) && animationSpeed != null) {
4441
- clock.multiplier = animationSpeed;
4402
+ };
4403
+ check(geometry);
4404
+ return safe;
4405
+ }
4406
+ function signedRingArea(points) {
4407
+ let sum = 0;
4408
+ for (let i = 0; i < points.length; i++) {
4409
+ const a = points[i];
4410
+ const b = points[(i + 1) % points.length];
4411
+ sum += a.longitude * b.latitude - b.longitude * a.latitude;
4412
+ }
4413
+ return sum / 2;
4414
+ }
4415
+ function isPointInRing(point, ring) {
4416
+ let inside = false;
4417
+ for (let i = 0, j = ring.length - 1; i < ring.length; j = i++) {
4418
+ const a = ring[i];
4419
+ const b = ring[j];
4420
+ if ((a.latitude > point.latitude) !== (b.latitude > point.latitude)
4421
+ && point.longitude < (b.longitude - a.longitude) * (point.latitude - a.latitude) / (b.latitude - a.latitude) + a.longitude) {
4422
+ inside = !inside;
4442
4423
  }
4443
- if (isAnimating != null) {
4444
- clock.shouldAnimate = isAnimating;
4424
+ }
4425
+ return inside;
4426
+ }
4427
+ /**
4428
+ * Runs through all found polygons and runs unkink through turf on them.
4429
+ * @param feature
4430
+ */
4431
+ function untangleFeature(feature) {
4432
+ // Collection to add to because the result might be multiple from an unkink.
4433
+ const collection = {
4434
+ geometries: [],
4435
+ type: "GeometryCollection"
4436
+ };
4437
+ // Runs a dedupe and unkink on the coordinates.
4438
+ // Returns if the coordinates were added to the collection.
4439
+ const processCoordinates = (coords) => {
4440
+ try {
4441
+ // Dedupe the coordinates to avoid issues with unkink.
4442
+ coords = dedupeCoordinates(coords);
4443
+ const outer = [];
4444
+ let inner = [];
4445
+ // We'll unkink each ring separately as this is killing the holes when it is done as a whole.
4446
+ // So we'll do it separate then recombine.
4447
+ for (let i = 0; i < coords.length; i++) {
4448
+ const ring = coords[i];
4449
+ const unkink = turf.unkinkPolygon({
4450
+ type: "Polygon",
4451
+ coordinates: [ring]
4452
+ });
4453
+ if (unkink.type == "FeatureCollection") {
4454
+ let target = i == 0 ? outer : inner;
4455
+ for (let j = 0; j < unkink.features.length; j++) {
4456
+ const unkinked = unkink.features[j].geometry.coordinates;
4457
+ if (unkinked.length > 0) {
4458
+ target.push(unkinked[0]);
4459
+ }
4460
+ }
4461
+ }
4462
+ else {
4463
+ console.error("Unexpected unkink result.", unkink);
4464
+ }
4465
+ }
4466
+ // Recreate the rings and reapply to the collection.
4467
+ if (outer.length > 0) {
4468
+ // Unkinking a self touching boundary splits it into pieces. Keeping whichever piece
4469
+ // happened to come back first can discard most of the shape, so keep the biggest one.
4470
+ let keep = outer[0];
4471
+ if (outer.length > 1) {
4472
+ let best = Math.abs(ringArea(keep));
4473
+ for (let i = 1; i < outer.length; i++) {
4474
+ const area = Math.abs(ringArea(outer[i]));
4475
+ if (area > best) {
4476
+ best = area;
4477
+ keep = outer[i];
4478
+ }
4479
+ }
4480
+ }
4481
+ const combinedCoords = [keep];
4482
+ for (let i = 0; i < inner.length; i++) {
4483
+ // A hole belonging to a piece that was just discarded is no longer inside anything,
4484
+ // and a hole crossing the boundary is what tears the fill.
4485
+ if (isRingInsideRing(inner[i], keep)) {
4486
+ combinedCoords.push(inner[i]);
4487
+ }
4488
+ }
4489
+ // Add the combined coordinates to the collection
4490
+ const polygon = {
4491
+ type: "Polygon",
4492
+ coordinates: combinedCoords
4493
+ };
4494
+ // Ensure right-hand rule is followed.
4495
+ ensureRightHandRule(polygon);
4496
+ // Add to the collection.
4497
+ collection.geometries.push(polygon);
4498
+ return true;
4499
+ }
4445
4500
  }
4446
- viewer.scene.requestRender();
4447
- clock[CESIUM_TIMELINE_KEY] = true;
4448
- if (livePaddingSeconds != null) {
4449
- clock[CESIUM_TIMELINE_LIVE_PADDING_KEY] = livePaddingSeconds || DEFAULT_LIVE_PADDING_SECONDS;
4501
+ catch (e) {
4502
+ // console.error("Failed to unkink polygon.", e);
4450
4503
  }
4451
- if (isLive != null) {
4452
- clock[CESIUM_TIMELINE_LIVE_KEY] = params.isLive == true;
4504
+ return false;
4505
+ };
4506
+ const processGeometry = (geometry) => {
4507
+ let added = false;
4508
+ if (geometry.type == "Polygon") {
4509
+ added = processCoordinates(geometry.coordinates);
4453
4510
  }
4454
- if (clock[CESIUM_TIMELINE_LIVE_KEY]) {
4455
- startLive(viewer);
4511
+ else if (geometry.type == "MultiPolygon") {
4512
+ for (let i = 0; i < geometry.coordinates.length; i++) {
4513
+ added = processCoordinates(geometry.coordinates[i]) || added;
4514
+ }
4456
4515
  }
4457
- else {
4458
- stopLive(viewer);
4516
+ if (!added) {
4517
+ // Adding original since we can't unkink it.
4518
+ collection.geometries.push(geometry);
4459
4519
  }
4520
+ };
4521
+ if (feature.geometry.type == "GeometryCollection") {
4522
+ feature.geometry.geometries.forEach((geometry) => {
4523
+ processGeometry(geometry);
4524
+ });
4460
4525
  }
4461
- ViewUtils.SetTimeDetails = SetTimeDetails;
4462
- function startLive(viewer) {
4463
- const doUpdate = () => {
4464
- if (!viewer || viewer.isDestroyed() || !viewer.scene) {
4465
- stopLive(viewer);
4466
- return;
4526
+ else {
4527
+ processGeometry(feature.geometry);
4528
+ }
4529
+ // Re-assign the geometry.
4530
+ if (collection.geometries.length == 1) {
4531
+ feature.geometry = collection.geometries[0];
4532
+ }
4533
+ else {
4534
+ feature.geometry = collection;
4535
+ }
4536
+ }
4537
+ /**
4538
+ * Runs through all found polygons and unions them using turf.
4539
+ * Failed unions are ignored and the original is kept.
4540
+ * @param feature
4541
+ */
4542
+ function unionFeature(feature) {
4543
+ // Collection to add to because the result might be multiple from an unkink.
4544
+ const collection = {
4545
+ geometries: [],
4546
+ type: "GeometryCollection"
4547
+ };
4548
+ // We'll turn each geometry into a feature and union them.
4549
+ const tmpCollection = {
4550
+ features: [],
4551
+ type: "FeatureCollection"
4552
+ };
4553
+ if (feature.geometry.type == "GeometryCollection") {
4554
+ feature.geometry.geometries.forEach((geometry) => {
4555
+ if (geometry.type == "Polygon") {
4556
+ tmpCollection.features.push({
4557
+ type: "Feature",
4558
+ geometry: geometry,
4559
+ properties: {}
4560
+ });
4467
4561
  }
4468
- // Get the current settings.
4469
- const tDetails = GetTimeDetails({ viewer });
4470
- const clock = viewer.clock;
4471
- if (clock) {
4472
- clock.shouldAnimate = true;
4473
- clock.multiplier = 1;
4474
- clock.currentTime = JulianDate.now();
4475
- clock.startTime = JulianDate.addSeconds(clock.currentTime, -tDetails.livePaddingSeconds, new JulianDate());
4476
- clock.stopTime = JulianDate.addSeconds(clock.currentTime, tDetails.livePaddingSeconds, new JulianDate());
4477
- clock.clockRange = ClockRange.UNBOUNDED;
4562
+ else if (geometry.type == "MultiPolygon") {
4563
+ for (let i = 0; i < geometry.coordinates.length; i++) {
4564
+ tmpCollection.features.push({
4565
+ type: "Feature",
4566
+ geometry: {
4567
+ type: "Polygon",
4568
+ coordinates: geometry.coordinates[i]
4569
+ },
4570
+ properties: {}
4571
+ });
4572
+ }
4478
4573
  }
4479
- };
4480
- if (viewer[CESIUM_TIMELINE_INTERVAL_KEY]) {
4481
- doUpdate();
4482
- return;
4483
- }
4484
- // We'll start an interval that occasionally updates the Cesium clock to stay in the desired settings.
4485
- // Since it moves live (1 second per second), we don't have to worry about the ranges being out of date quickly.
4486
- viewer[CESIUM_TIMELINE_INTERVAL_KEY] = setInterval(() => {
4487
- doUpdate();
4488
- }, 800);
4489
- viewer[CESIUM_TIMELINE_LIVE_KEY] = true;
4490
- // Initial update.
4491
- doUpdate();
4574
+ // Only focusing on polygons.
4575
+ else {
4576
+ collection.geometries.push(geometry);
4577
+ }
4578
+ });
4492
4579
  }
4493
- function stopLive(viewer) {
4494
- if (!viewer) {
4495
- return;
4496
- }
4497
- let interval = viewer[CESIUM_TIMELINE_INTERVAL_KEY];
4498
- if (interval) {
4499
- clearInterval(interval);
4500
- viewer[CESIUM_TIMELINE_INTERVAL_KEY] = null;
4580
+ else if (feature.geometry.type == "Polygon") {
4581
+ tmpCollection.features.push({
4582
+ type: "Feature",
4583
+ geometry: feature.geometry,
4584
+ properties: {}
4585
+ });
4586
+ }
4587
+ else if (feature.geometry.type == "MultiPolygon") {
4588
+ for (let i = 0; i < feature.geometry.coordinates.length; i++) {
4589
+ tmpCollection.features.push({
4590
+ type: "Feature",
4591
+ geometry: {
4592
+ type: "Polygon",
4593
+ coordinates: feature.geometry.coordinates[i]
4594
+ },
4595
+ properties: {}
4596
+ });
4501
4597
  }
4502
- viewer[CESIUM_TIMELINE_LIVE_KEY] = false;
4503
4598
  }
4504
- function SetGlobeDetails(params) {
4505
- let { viewer, hidden, baseColor } = params;
4506
- const scene = viewer === null || viewer === void 0 ? void 0 : viewer.scene;
4507
- if (!(scene === null || scene === void 0 ? void 0 : scene.globe)) {
4508
- return;
4599
+ // No polygons to union.
4600
+ // Need at least 2 to union.
4601
+ if (tmpCollection.features.length < 2) {
4602
+ return;
4603
+ }
4604
+ // Now we'll union them.
4605
+ try {
4606
+ const union = turf.union(tmpCollection);
4607
+ if (union.geometry.type == "Polygon") {
4608
+ collection.geometries.push(union.geometry);
4509
4609
  }
4510
- if (hidden == null) {
4511
- hidden = !scene.globe.show;
4610
+ else if (union.geometry.type == "MultiPolygon") {
4611
+ for (let i = 0; i < union.geometry.coordinates.length; i++) {
4612
+ collection.geometries.push({
4613
+ type: "Polygon",
4614
+ coordinates: union.geometry.coordinates[i]
4615
+ });
4616
+ }
4512
4617
  }
4513
4618
  else {
4514
- scene.globe.show = !hidden;
4515
- }
4516
- if (baseColor == null) {
4517
- baseColor = scene.globe.baseColor;
4619
+ // Returning early because the result is unexpected.
4620
+ return;
4518
4621
  }
4519
- // When globe is off, we'll also hide the stars/moon.
4520
- // We also grab the globe color and apply it to the sky.
4521
- if (hidden && GetModelSpace(viewer)) {
4522
- scene.skyBox.show = false;
4523
- scene.skyAtmosphere.show = false;
4524
- scene.sun.show = false;
4525
- scene.moon.show = false;
4526
- scene.backgroundColor = baseColor.clone();
4622
+ }
4623
+ catch (e) {
4624
+ // console.error("Failed to union polygons.", e);
4625
+ return;
4626
+ }
4627
+ // Re-assign the geometry.
4628
+ if (collection.geometries.length == 1) {
4629
+ feature.geometry = collection.geometries[0];
4630
+ }
4631
+ else {
4632
+ feature.geometry = collection;
4633
+ }
4634
+ }
4635
+ function ringArea(ring) {
4636
+ let sum = 0;
4637
+ for (let i = 0; i < ring.length; i++) {
4638
+ const a = ring[i];
4639
+ const b = ring[(i + 1) % ring.length];
4640
+ sum += a[0] * b[1] - b[0] * a[1];
4641
+ }
4642
+ return sum / 2;
4643
+ }
4644
+ function isRingInsideRing(inner, outer) {
4645
+ for (let i = 0; i < inner.length; i++) {
4646
+ let inside = false;
4647
+ for (let a = 0, b = outer.length - 1; a < outer.length; b = a++) {
4648
+ if ((outer[a][1] > inner[i][1]) !== (outer[b][1] > inner[i][1])
4649
+ && inner[i][0] < (outer[b][0] - outer[a][0]) * (inner[i][1] - outer[a][1]) / (outer[b][1] - outer[a][1]) + outer[a][0]) {
4650
+ inside = !inside;
4651
+ }
4527
4652
  }
4528
- else {
4529
- scene.skyBox.show = true;
4530
- scene.skyAtmosphere.show = true;
4531
- scene.sun.show = true;
4532
- scene.moon.show = true;
4533
- scene.backgroundColor = Color.BLACK;
4653
+ if (!inside) {
4654
+ return false;
4534
4655
  }
4535
- scene.globe.baseColor = baseColor;
4536
4656
  }
4537
- ViewUtils.SetGlobeDetails = SetGlobeDetails;
4538
- function SetModelSpace(viewer, modelSpace) {
4539
- if (!viewer) {
4540
- return;
4657
+ return true;
4658
+ }
4659
+ function dedupeCoordinates(inputCoords) {
4660
+ return inputCoords.map(ring => {
4661
+ if (ring.length < 2) {
4662
+ return ring;
4541
4663
  }
4542
- if (viewer[CESIUM_MODEL_SPACE_KEY] === modelSpace) {
4543
- return;
4664
+ const dedupeCoords = [];
4665
+ const uniqueCoords = new Set();
4666
+ // Dedupe the points.
4667
+ ring.forEach(coord => {
4668
+ const key = coord.join(',');
4669
+ if (!uniqueCoords.has(key)) {
4670
+ uniqueCoords.add(key);
4671
+ dedupeCoords.push(coord);
4672
+ }
4673
+ });
4674
+ // Make sure the last point matches the first.
4675
+ if (dedupeCoords.length > 1) {
4676
+ if (dedupeCoords[0][0] != dedupeCoords[dedupeCoords.length - 1][0] ||
4677
+ dedupeCoords[0][1] != dedupeCoords[dedupeCoords.length - 1][1]) {
4678
+ dedupeCoords.push(dedupeCoords[0]);
4679
+ }
4680
+ }
4681
+ return dedupeCoords;
4682
+ });
4683
+ }
4684
+ function ensureRightHandRule(polygon) {
4685
+ // Ensure the outer ring follows the right-hand rule
4686
+ if (polygon.coordinates.length > 0) {
4687
+ const outerRing = polygon.coordinates[0];
4688
+ if (isClockwise(outerRing)) {
4689
+ polygon.coordinates[0] = outerRing.reverse();
4544
4690
  }
4545
- viewer[CESIUM_MODEL_SPACE_KEY] = modelSpace;
4546
- // Reload globe since we display it differently between the two modes.
4547
- SetGlobeDetails({ viewer });
4548
4691
  }
4549
- ViewUtils.SetModelSpace = SetModelSpace;
4550
- function GetModelSpace(viewer) {
4551
- if (!viewer) {
4552
- return false;
4692
+ // Ensure any inner rings (holes) follow the right-hand rule
4693
+ for (let i = 1; i < polygon.coordinates.length; i++) {
4694
+ const innerRing = polygon.coordinates[i];
4695
+ if (!isClockwise(innerRing)) {
4696
+ polygon.coordinates[i] = innerRing.reverse();
4553
4697
  }
4554
- return Boolean(viewer[CESIUM_MODEL_SPACE_KEY]);
4555
4698
  }
4556
- ViewUtils.GetModelSpace = GetModelSpace;
4557
- })(ViewUtils || (ViewUtils = {}));
4699
+ }
4700
+ function isClockwise(ring) {
4701
+ let sum = 0;
4702
+ for (let i = 0; i < ring.length - 1; i++) {
4703
+ const p1 = ring[i];
4704
+ const p2 = ring[i + 1];
4705
+ sum += (p2[0] - p1[0]) * (p2[1] + p1[1]);
4706
+ }
4707
+ return sum > 0;
4708
+ }
4558
4709
 
4559
4710
  /*
4560
4711
  * Lets something decide WHEN a `show` flag is honoured, without owning WHAT it should be.
@@ -28916,6 +29067,7 @@ async function renderNavigator(iteration, params, bookmark, view, getters) {
28916
29067
  light.color = Color.fromCssColorString(lighting.color);
28917
29068
  light.intensity = EnsureNumber(lighting.intensity);
28918
29069
  }
29070
+ ViewUtils.ApplyDefaultBrightness(viewer, EnsureNumber(lighting.brightnessShift, DEFAULT_BRIGHTNESS_SHIFT));
28919
29071
  let quality = bSettings === null || bSettings === void 0 ? void 0 : bSettings.quality;
28920
29072
  if (quality == null) {
28921
29073
  quality = (_x = defaults === null || defaults === void 0 ? void 0 : defaults.settings) === null || _x === void 0 ? void 0 : _x.quality;
@@ -35109,6 +35261,8 @@ var ViewerUtils;
35109
35261
  viewer
35110
35262
  });
35111
35263
  }
35264
+ // Newer cesium is much dimmer by default so we shift brightness a bit.
35265
+ ViewUtils.ApplyDefaultBrightness(viewer);
35112
35266
  backgroundRendering(viewer);
35113
35267
  // Capturing the destroy call to destroy all widgets.
35114
35268
  const olDestroy = viewer.destroy;
@@ -43383,7 +43537,7 @@ var StyleUtils;
43383
43537
  StyleUtils.ApplyTypeStyle = ApplyTypeStyle;
43384
43538
  })(StyleUtils || (StyleUtils = {}));
43385
43539
 
43386
- const VERSION = "7.1.5";
43540
+ const VERSION = "7.1.7";
43387
43541
  /**
43388
43542
  * Updates the environment instance used by bruce-cesium to one specified.
43389
43543
  * This can be used to ensure that the instance a parent is referencing is shared between bruce-cesium, bruce-models, and the parent app.
@@ -43400,5 +43554,5 @@ const getENVIRONMENT = () => {
43400
43554
  return ENVIRONMENT;
43401
43555
  };
43402
43556
 
43403
- export { VERSION, setENVIRONMENT, getENVIRONMENT, CesiumAnimatedInOut, DisplacedSurfacePrimitive, CesiumAnimatedProperty, isStyleChanged, isOutlineChanged$1 as isOutlineChanged, StyleEffective, EntityRenderEngine, EntityRenderEngineModel3d, EntityRenderEnginePoint, EntityRenderEnginePolygon, EntityRenderEnginePolyline, MenuItemCreator, MenuItemManager, CesiumParabola, EntityLabel, LiveCursor, SharedGetters, DataSourceStaticKmlManager, DataLabRenderManager, EntitiesIdsRenderManager, EntitiesLoadedRenderManager, EntitiesRenderManager, EntityRenderManager, AssemblyRenderManager, GoogleSearchRenderManager, RelationsRenderManager, RenderManager, TilesetArbRenderManager, TilesetCadRenderManager, TilesetEntitiesRenderManager, TilesetGooglePhotosRenderManager, TilesetOsmRenderManager, TilesetPointcloudRenderManager, TileRenderEngine, createTileset, TilesetRenderEngine, ViewRenderEngine, VisualRegisterCuller, VisualsRegister, XGridsRenderEngine, CesiumEntityStyler, DrawingUtils, EntityUtils, MeasureUtils, StyleUtils, CESIUM_INSPECTOR_KEY, CESIUM_TIMELINE_KEY, CESIUM_TIMELINE_LIVE_KEY, CESIUM_TIMELINE_LIVE_PADDING_KEY, CESIUM_TIMELINE_INTERVAL_KEY, CESIUM_MODEL_SPACE_KEY, DEFAULT_LIVE_PADDING_SECONDS, ViewUtils, CesiumViewMonitor, ViewGroundArea, ViewerEventTracker, ViewerUtils, Draw3dPolygon, Draw3dPolyline, MeasureCreator, Walkthrough, WidgetControlViewBar, WidgetControlViewBarSearch, WidgetLeftPanelTab, WidgetLeftPanelTabBookmarks, WidgetLeftPanelTabDashboard, EMenuItemState, WidgetLeftPanelTabMenuItems, Widget, VIEWER_BOOKMARKS_WIDGET_KEY, WidgetBookmarks, WidgetBranding, WidgetCursorBar, WidgetEmbeddedInfoView, WidgetInfoView, VIEWER_LEFT_PANEL_WIDGET_KEY, VIEWER_LEFT_PANEL_CSS_VAR_LEFT, WidgetLeftPanel, WidgetNavCompass$$1 as WidgetNavCompass, VIEWER_VIEW_BAR_WIDGET_KEY, WidgetViewBar };
43557
+ export { VERSION, setENVIRONMENT, getENVIRONMENT, CesiumAnimatedInOut, DisplacedSurfacePrimitive, CesiumAnimatedProperty, isStyleChanged, isOutlineChanged$1 as isOutlineChanged, StyleEffective, EntityRenderEngine, EntityRenderEngineModel3d, EntityRenderEnginePoint, EntityRenderEnginePolygon, EntityRenderEnginePolyline, MenuItemCreator, MenuItemManager, CesiumParabola, EntityLabel, LiveCursor, SharedGetters, DataSourceStaticKmlManager, DataLabRenderManager, EntitiesIdsRenderManager, EntitiesLoadedRenderManager, EntitiesRenderManager, EntityRenderManager, AssemblyRenderManager, GoogleSearchRenderManager, RelationsRenderManager, RenderManager, TilesetArbRenderManager, TilesetCadRenderManager, TilesetEntitiesRenderManager, TilesetGooglePhotosRenderManager, TilesetOsmRenderManager, TilesetPointcloudRenderManager, TileRenderEngine, createTileset, TilesetRenderEngine, ViewRenderEngine, VisualRegisterCuller, VisualsRegister, XGridsRenderEngine, CesiumEntityStyler, DrawingUtils, EntityUtils, MeasureUtils, StyleUtils, CESIUM_INSPECTOR_KEY, CESIUM_TIMELINE_KEY, CESIUM_TIMELINE_LIVE_KEY, CESIUM_TIMELINE_LIVE_PADDING_KEY, CESIUM_TIMELINE_INTERVAL_KEY, CESIUM_MODEL_SPACE_KEY, DEFAULT_LIVE_PADDING_SECONDS, DEFAULT_BRIGHTNESS_SHIFT, ViewUtils, CesiumViewMonitor, ViewGroundArea, ViewerEventTracker, ViewerUtils, Draw3dPolygon, Draw3dPolyline, MeasureCreator, Walkthrough, WidgetControlViewBar, WidgetControlViewBarSearch, WidgetLeftPanelTab, WidgetLeftPanelTabBookmarks, WidgetLeftPanelTabDashboard, EMenuItemState, WidgetLeftPanelTabMenuItems, Widget, VIEWER_BOOKMARKS_WIDGET_KEY, WidgetBookmarks, WidgetBranding, WidgetCursorBar, WidgetEmbeddedInfoView, WidgetInfoView, VIEWER_LEFT_PANEL_WIDGET_KEY, VIEWER_LEFT_PANEL_CSS_VAR_LEFT, WidgetLeftPanel, WidgetNavCompass$$1 as WidgetNavCompass, VIEWER_VIEW_BAR_WIDGET_KEY, WidgetViewBar };
43404
43558
  //# sourceMappingURL=bruce-cesium.es5.js.map