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