@masterportal/masterportalapi 2.1.1

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.
Files changed (92) hide show
  1. package/.editorconfig +15 -0
  2. package/.eslintignore +6 -0
  3. package/.eslintrc +184 -0
  4. package/.husky/pre-push +4 -0
  5. package/CHANGELOG.md +217 -0
  6. package/License.txt +21 -0
  7. package/README.md +24 -0
  8. package/babel.config.json +6 -0
  9. package/example/README.md +7 -0
  10. package/example/config/localGeoJSON.js +956 -0
  11. package/example/config/portal.json +35 -0
  12. package/example/config/services.json +79 -0
  13. package/example/index.html +27 -0
  14. package/example/index.js +210 -0
  15. package/example/style.scss +59 -0
  16. package/jest.config.js +18 -0
  17. package/jest.setup.js +5 -0
  18. package/jsdoc.json +15 -0
  19. package/package.json +62 -0
  20. package/public/marker.svg +1 -0
  21. package/public/stringMarker.js +5 -0
  22. package/src/crs.js +122 -0
  23. package/src/defaults.js +38 -0
  24. package/src/index.js +30 -0
  25. package/src/layer/geojson/index.js +109 -0
  26. package/src/layer/geojson/style.js +61 -0
  27. package/src/layer/lib.js +32 -0
  28. package/src/layer/oaf.js +207 -0
  29. package/src/layer/terrain.js +72 -0
  30. package/src/layer/tileset.js +71 -0
  31. package/src/layer/vector.js +48 -0
  32. package/src/layer/vectorBase.js +39 -0
  33. package/src/layer/wfs.js +218 -0
  34. package/src/layer/wms.js +185 -0
  35. package/src/lib/coordsToPairs.js +15 -0
  36. package/src/lib/getInitialLayers.js +22 -0
  37. package/src/lib/load3DScript.js +22 -0
  38. package/src/lib/oafUtil.js +22 -0
  39. package/src/lib/setBackgroundImage.js +23 -0
  40. package/src/lib/wfsUtil.js +75 -0
  41. package/src/lib/zoomTo.js +40 -0
  42. package/src/maps/api.js +5 -0
  43. package/src/maps/map.js +35 -0
  44. package/src/maps/mapView.js +54 -0
  45. package/src/maps/ol/olMap.js +124 -0
  46. package/src/maps/olcs/3dUtils/fixedOverlaySynchronizer.js +39 -0
  47. package/src/maps/olcs/3dUtils/wmsRasterSynchronizer.js +348 -0
  48. package/src/maps/olcs/olcsMap.js +212 -0
  49. package/src/rawLayerList.js +88 -0
  50. package/src/searchAddress/gazetteerUrl.js +22 -0
  51. package/src/searchAddress/index.js +13 -0
  52. package/src/searchAddress/parse.js +196 -0
  53. package/src/searchAddress/search.js +184 -0
  54. package/src/searchAddress/searchGazetteer.js +52 -0
  55. package/src/searchAddress/showGeographicIdentifier.js +20 -0
  56. package/src/searchAddress/types.js +17 -0
  57. package/test/.eslintrc +7 -0
  58. package/test/crs.test.js +109 -0
  59. package/test/layer/geojson/index.test.js +133 -0
  60. package/test/layer/geojson/style.test.js +46 -0
  61. package/test/layer/lib.test.js +83 -0
  62. package/test/layer/oaf.test.js +245 -0
  63. package/test/layer/resources/oafFeatures.js +105 -0
  64. package/test/layer/resources/wfsFeatures.js +26 -0
  65. package/test/layer/resources/wfsFilter.js +17 -0
  66. package/test/layer/terrain.test.js +106 -0
  67. package/test/layer/tileset.test.js +116 -0
  68. package/test/layer/vector.test.js +76 -0
  69. package/test/layer/vectorBase.test.js +48 -0
  70. package/test/layer/wfs.test.js +388 -0
  71. package/test/layer/wms.test.js +256 -0
  72. package/test/lib/coordsToPairs.test.js +9 -0
  73. package/test/lib/getInitialLayers.test.js +28 -0
  74. package/test/lib/oafUtil.test.js +24 -0
  75. package/test/lib/setBackgroundImage.test.js +49 -0
  76. package/test/lib/wfsUtil.test.js +28 -0
  77. package/test/lib/zoomTo.test.js +74 -0
  78. package/test/map.test.js +258 -0
  79. package/test/mapView.test.js +59 -0
  80. package/test/rawLayerList.test.js +48 -0
  81. package/test/searchAddress/gazetteerSearchResults/address.js +175 -0
  82. package/test/searchAddress/gazetteerSearchResults/district.js +71 -0
  83. package/test/searchAddress/gazetteerSearchResults/houseNumber.js +32 -0
  84. package/test/searchAddress/gazetteerSearchResults/index.js +19 -0
  85. package/test/searchAddress/gazetteerSearchResults/parcel.js +44 -0
  86. package/test/searchAddress/gazetteerSearchResults/street.js +46 -0
  87. package/test/searchAddress/gazetteerSearchResults/streetKey.js +51 -0
  88. package/test/searchAddress/gazetteerUrl.test.js +22 -0
  89. package/test/searchAddress/parse.test.js +110 -0
  90. package/test/searchAddress/search.test.js +150 -0
  91. package/test/searchAddress/searchGazetteer.test.js +58 -0
  92. package/test/searchAddress/showGeographicIdentifier.test.js +22 -0
@@ -0,0 +1,35 @@
1
+ import * as olMap from "./ol/olMap.js";
2
+ import * as olcsMap from "./olcs/olcsMap.js";
3
+
4
+ export default {
5
+ /**
6
+ * Creates a map and adds it to the mapCollection. Depending on param 'mapMode' a 2D or a 3D map is created. Default ist 2D.
7
+ * @param {object} [config] - configuration object - falls back to defaults if none given
8
+ * @param {string} [config.target="map"] - div id to render map to
9
+ * @param {string} [config.namedProjections] - projections to create the map
10
+ * @param {string} [config.backgroundImage] - background image for map; "" to use none
11
+ * @param {string} [config.epsg] - CRS to use
12
+ * @param {number[]} [config.extent] - extent to use
13
+ * @param {Array.<{resolution: number, scale: number, zoomLevel: number}>} [config.options] - zoom level definition
14
+ * @param {Array.<string[]>} [config.options] - each sub-array has two values: projection name, and projection description
15
+ * @param {number} [config.startResolution] - initial resolution
16
+ * @param {number[]} [config.startCenter] - initial position
17
+ * @param {(string|object)} [config.layerConf] - services registry or URL thereof
18
+ * @param {string} [config.gazetteerUrl] - url of gazetteer to use in searchAddress
19
+ * @param {String} [mapMode = "2D"] The map mode. '2D' to create a 2D-map and '3D' to create a 3D-map.
20
+ * @param {object} [settings={}] - settings object
21
+ * @param {object} [settings.mapParams] - additional parameter object that is spread into the ol.Map constructor object
22
+ * @param {function} [settings.callback] - optional callback for layer list loading
23
+ * @returns {module:ol/PluggableMap~PluggableMap} The map.
24
+ */
25
+ createMap: function (config, mapMode = "2D", settings = {}) {
26
+ const createMapFunctions = {
27
+ "2D": olMap.createMap,
28
+ "3D": olcsMap.createMap
29
+ },
30
+ map = createMapFunctions[mapMode](config, settings);
31
+
32
+ return map;
33
+ },
34
+ olcsMap
35
+ };
@@ -0,0 +1,54 @@
1
+ import {View} from "ol";
2
+ import defaults from "../defaults";
3
+
4
+ /**
5
+ * Sets the startResolution or the startZoomlevel, depending on the configuration.
6
+ * Where the resolution is preferred.
7
+ * The value to use is set and the other is undefined.
8
+ * @param {object} config - configuration object
9
+ * @param {object} [mergedConfig=defaults] - configuration from object merged with default configuration
10
+ * @returns {object} object that contains startZoomLevel and startResolution
11
+ */
12
+ export function chooseZoomOrResolution (config = {}, mergedConfig = defaults) {
13
+ const zoomResolution = {
14
+ startZoomLevel: undefined,
15
+ startResolution: undefined
16
+ };
17
+
18
+ if (Object.prototype.hasOwnProperty.call(config, "startZoomLevel") && !Object.prototype.hasOwnProperty.call(config, "startResolution")) {
19
+ zoomResolution.startZoomLevel = mergedConfig.startZoomLevel;
20
+ }
21
+ else {
22
+ zoomResolution.startResolution = mergedConfig.startResolution;
23
+ }
24
+
25
+ return zoomResolution;
26
+ }
27
+
28
+ /**
29
+ * Creates a View from config.
30
+ * @param {object} config - configuration object
31
+ * @param {string} [config.epsg="EPSG:25832"] - CRS to use
32
+ * @param {number[]} [config.extent=[510000.0, 5850000.0, 625000.4, 6000000.0]] - extent to use
33
+ * @param {Array.<string[]>} [config.options=[{resolution: 66.14579761460263, scale: 250000, zoomLevel: 0},{resolution: 26.458319045841044, scale: 100000, zoomLevel: 1},{resolution: 15.874991427504629, scale: 60000, zoomLevel: 2},{resolution: 10.583327618336419, scale: 40000, zoomLevel: 3},{resolution: 5.2916638091682096, scale: 20000, zoomLevel: 4},{resolution: 2.6458319045841048, scale: 10000, zoomLevel: 5},{resolution: 1.3229159522920524, scale: 5000, zoomLevel: 6},{resolution: 0.6614579761460262, scale: 2500, zoomLevel: 7},{resolution: 0.2645831904584105, scale: 1000, zoomLevel: 8},{resolution: 0.13229159522920521, scale: 500, zoomLevel: 9}]] - each sub-array has two values: projection name, and projection description
34
+ * @param {number} [config.startResolution=15.874991427504629] - initial resolution
35
+ * @param {number[]} [config.startCenter=[565874, 5934140]] - initial position
36
+ * @returns {ol.View} view with start values from config
37
+ */
38
+ export function createMapView (config) {
39
+ const mergedConfig = Object.assign({}, defaults, config),
40
+ zoomResolution = chooseZoomOrResolution(config, mergedConfig);
41
+
42
+ return new View({
43
+ projection: mergedConfig.epsg,
44
+ center: mergedConfig.startCenter,
45
+ extent: mergedConfig.extent,
46
+ zoom: zoomResolution.startZoomLevel,
47
+ options: mergedConfig.options,
48
+ resolution: zoomResolution.startResolution,
49
+ resolutions: mergedConfig.options.map(entry => entry.resolution),
50
+ constrainResolution: true,
51
+ constrainOnlyCenter: true,
52
+ backgroundImage: mergedConfig.backgroundImage
53
+ });
54
+ }
@@ -0,0 +1,124 @@
1
+ import {Map, PluggableMap} from "ol";
2
+ import {defaults as olDefaultInteractions} from "ol/interaction.js";
3
+ import setBackgroundImage from "../../lib/setBackgroundImage";
4
+ import getInitialLayers from "../../lib/getInitialLayers";
5
+ import defaults from "../../defaults";
6
+ import * as wms from "../../layer/wms";
7
+ import * as geojson from "../../layer/geojson";
8
+ import * as wfs from "../../layer/wfs";
9
+ import * as vectorBase from "../../layer/vectorBase";
10
+ import * as oaf from "../../layer/oaf";
11
+ import {createMapView} from "../../maps/mapView";
12
+ import {initializeLayerList, getLayerWhere} from "../../rawLayerList";
13
+ import {registerProjections} from "../../crs";
14
+ import {setGazetteerUrl} from "../../searchAddress";
15
+
16
+ let mapIdCounter = 0;
17
+
18
+ /**
19
+ * lookup for layer constructors
20
+ * @ignore
21
+ */
22
+ const layerBuilderMap = {
23
+ wms,
24
+ wfs,
25
+ geojson,
26
+ vectorBase,
27
+ oaf
28
+ },
29
+ originalAddLayer = PluggableMap.prototype.addLayer;
30
+
31
+ /**
32
+ * Adds a layer to the map, or adds a layer to the map by id.
33
+ * This id is looked up within the array of all known services.
34
+ *
35
+ * Make sure services have been loaded with a callback on createMap
36
+ * if you request the services from the internet.
37
+ *
38
+ * This function is available on all ol/Map instances.
39
+ * @param {(string|ol/Layer)} layerOrId - if of layer to add to map
40
+ * @param {object} [params] - optional parameter object
41
+ * @param {boolean} [params.visibility=true] - whether added layer is initially visible
42
+ * @param {Number} [params.transparency=0] - how visible the layer is initially
43
+ * @returns {?ol.Layer} added layer
44
+ */
45
+ function addLayer (layerOrId, params = {visibility: true, transparency: 0}) {
46
+ var layer, layerBuilder;
47
+
48
+ // if parameter is id, create and add layer with masterportalAPI mechanisms
49
+ if (typeof layerOrId === "string") {
50
+ const rawLayer = getLayerWhere({id: layerOrId});
51
+
52
+ if (!rawLayer) {
53
+ console.error("Layer with id '" + layerOrId + "' not found. No layer added to map.");
54
+ return null;
55
+ }
56
+ layerBuilder = layerBuilderMap[rawLayer.typ.toLowerCase()];
57
+ if (!layerBuilder) {
58
+ console.error("Layer with id '" + layerOrId + "' has unknown type '" + rawLayer.typ + "'. No layer added to map.");
59
+ return null;
60
+ }
61
+ layer = layerBuilder.createLayer(rawLayer, {}, {map: this});
62
+ layer.setVisible(typeof params.visibility === "boolean" ? params.visibility : true);
63
+ layer.setOpacity(typeof params.transparency === "number" ? (100 - params.transparency) / 100 : 1);
64
+ originalAddLayer.call(this, layer);
65
+ return layer;
66
+ }
67
+
68
+ // else use original function
69
+ return originalAddLayer.call(this, layerOrId);
70
+ }
71
+
72
+ PluggableMap.prototype.addLayer = addLayer;
73
+
74
+ /**
75
+ * Creates an openlayers map according to configuration. Does not set many default values itself, but uses function that do.
76
+ * Check the called functions for default values, or [the defaults file]{@link ./defaults.js}.
77
+ * @param {object} [config] - configuration object - falls back to defaults if none given
78
+ * @param {string} [config.target="map"] - div id to render map to
79
+ * @param {string} [config.namedProjections] - projections to create the map
80
+ * @param {string} [config.backgroundImage] - background image for map; "" to use none
81
+ * @param {string} [config.epsg] - CRS to use
82
+ * @param {number[]} [config.extent] - extent to use
83
+ * @param {Array.<{resolution: number, scale: number, zoomLevel: number}>} [config.options] - zoom level definition
84
+ * @param {Array.<string[]>} [config.options] - each sub-array has two values: projection name, and projection description
85
+ * @param {number} [config.startResolution] - initial resolution
86
+ * @param {number[]} [config.startCenter] - initial position
87
+ * @param {(string|object)} [config.layerConf] - services registry or URL thereof
88
+ * @param {string} [config.gazetteerUrl] - url of gazetteer to use in searchAddress
89
+ * @param {object} [settings={}] - setings object
90
+ * @param {object} [settings.mapParams] - additional parameter object that is spread into the ol.Map constructor object
91
+ * @param {function} [settings.callback] - optional callback for layer list loading
92
+ * @param {String} [mapMode = "2D"] The map mode. '2D' to craete a 2D-map and '3D' to create a 3D-map.
93
+ * @returns {object} map object from ol
94
+ */
95
+ export function createMap (config = defaults, {mapParams, callback} = {}) {
96
+ registerProjections(config.namedProjections);
97
+ setBackgroundImage(config);
98
+ setGazetteerUrl(config.gazetteerUrl);
99
+ const map = new Map(Object.assign({
100
+ target: config.target || defaults.target,
101
+ interactions: olDefaultInteractions({altShiftDragRotate: false, pinchRotate: false}),
102
+ controls: [],
103
+ view: createMapView(config)
104
+ }, mapParams));
105
+
106
+ map.set("mapMode", "2D");
107
+ map.set("id", `map2D_${mapIdCounter++}`);
108
+
109
+ // extend callback to load configured initial layers
110
+ initializeLayerList(config.layerConf, (param, error) => {
111
+ getInitialLayers(config)
112
+ .forEach(layer => {
113
+ map.addLayer(layer.id, layer);
114
+ });
115
+
116
+ if (typeof callback === "function") {
117
+ return callback(param, error);
118
+ }
119
+
120
+ return null;
121
+ });
122
+
123
+ return map;
124
+ }
@@ -0,0 +1,39 @@
1
+ import OverlaySynchronizer from "olcs/OverlaySynchronizer.js";
2
+
3
+ /**
4
+ * Represents a FixedOverlaySynchronizer.
5
+ */
6
+ class FixedOverlaySynchronizer extends OverlaySynchronizer {
7
+ /* eslint-disable no-useless-constructor */
8
+ /**
9
+ * This object takes care of one-directional synchronization of
10
+ * Openlayers WMS raster layers to the given Cesium globe. This Synchronizer
11
+ * assumes that the given WMS supports EPSG Code 4326 (WGS84)
12
+ * @param {!ol.Map} map -
13
+ * @param {!Cesium.Scene} scene -
14
+ * @constructor
15
+ * @extends {olcs.AbstractSynchronizer.<Cesium.ImageryLayer>}
16
+ * @api
17
+ * @struct
18
+ */
19
+ constructor (map, scene) {
20
+ super(map, scene);
21
+ }
22
+
23
+ /**
24
+ * @api
25
+ * @returns {void}
26
+ */
27
+ addOverlays () {
28
+ /* eslint no-underscore-dangle: ["error", { "allow": ["overlays_"] }]*/
29
+ this.overlays_.forEach((overlay) => {
30
+ if (overlay.getId() !== undefined) {
31
+ this.addOverlay(overlay);
32
+ }
33
+ });
34
+ }
35
+ }
36
+
37
+ export default FixedOverlaySynchronizer;
38
+
39
+ /* eslint-enable no-useless-constructor */
@@ -0,0 +1,348 @@
1
+ /**
2
+ * @module olcs.WMSRasterSynchronizer
3
+ */
4
+ import olLayerGroup from "ol/layer/Group.js";
5
+ import {getUid} from "olcs/util.js";
6
+ import TileWMS from "ol/source/TileWMS.js";
7
+ import olcsAbstractSynchronizer from "olcs/AbstractSynchronizer.js";
8
+ import olcsCore from "olcs/core.js";
9
+ import {Tile, Image as ImageLayer} from "ol/layer.js";
10
+ import {stableSort} from "ol/array.js";
11
+ import {getBottomLeft, getBottomRight, getTopRight, getTopLeft} from "ol/extent.js";
12
+ import {transformExtent} from "ol/proj.js";
13
+ import StaticImageSource from "ol/source/ImageStatic";
14
+ import proj4 from "proj4";
15
+
16
+ /**
17
+ * Represents a WMSRasterSynchronizer.
18
+ */
19
+ class WMSRasterSynchronizer extends olcsAbstractSynchronizer {
20
+ /**
21
+ * This object takes care of one-directional synchronization of
22
+ * Openlayers WMS raster layers to the given Cesium globe. This Synchronizer
23
+ * assumes that the given WMS supports EPSG Code 4326 (WGS84)
24
+ * @param {!ol.Map} map -
25
+ * @param {!Cesium.Scene} scene -
26
+ * @constructor
27
+ * @extends {olcs.AbstractSynchronizer.<Cesium.ImageryLayer>}
28
+ * @api
29
+ * @struct
30
+ */
31
+ constructor (map, scene) {
32
+ super(map, scene);
33
+ /**
34
+ * @type {!Cesium.ImageryLayerCollection}
35
+ * @private
36
+ */
37
+ this.cesiumLayers = scene.imageryLayers;
38
+
39
+ /**
40
+ * @type {!Cesium.ImageryLayerCollection}
41
+ * @private
42
+ */
43
+ /* eslint-disable no-undef */
44
+ this.ourLayers = new Cesium.ImageryLayerCollection();
45
+ }
46
+
47
+
48
+ /**
49
+ * @inheritDoc
50
+ */
51
+ addCesiumObject (object) {
52
+ this.cesiumLayers.add(object);
53
+ this.ourLayers.add(object);
54
+ }
55
+
56
+
57
+ /**
58
+ * @inheritDoc
59
+ */
60
+ destroyCesiumObject (object) {
61
+ object.destroy();
62
+ }
63
+
64
+
65
+ /**
66
+ * @inheritDoc
67
+ */
68
+ removeSingleCesiumObject (object, destroy) {
69
+ this.cesiumLayers.remove(object, destroy);
70
+ this.ourLayers.remove(object, false);
71
+ }
72
+
73
+
74
+ /**
75
+ * @inheritDoc
76
+ */
77
+ removeAllCesiumObjects (destroy) {
78
+ for (let i = 0; i < this.ourLayers.length; ++i) {
79
+ this.cesiumLayers.remove(this.ourLayers.get(i), destroy);
80
+ }
81
+ this.ourLayers.removeAll(false);
82
+ }
83
+
84
+
85
+ /**
86
+ * Creates an array of Cesium.ImageryLayer.
87
+ * May be overriden by child classes to implement custom behavior.
88
+ * The default implementation handles tiled imageries in EPSG:4326 or
89
+ * EPSG:3859.
90
+ * @param {!ol.layer.Base} olLayer -
91
+ * @param {?ol.proj.Projection} viewProj Projection of the view.
92
+ * @return {?Array.<!Cesium.ImageryLayer>} array or null if not possible
93
+ * (or supported)
94
+ * @protected
95
+ */
96
+ convertLayerToCesiumImageries (olLayer, viewProj) {
97
+ let layerOptions = {
98
+ "show": false
99
+ },
100
+ source = {},
101
+ cesiumLayer = {},
102
+ provider = null;
103
+
104
+ if (!(olLayer instanceof Tile) && !(olLayer instanceof ImageLayer)) {
105
+ return null;
106
+ }
107
+
108
+ source = olLayer.getSource();
109
+
110
+ if (source instanceof TileWMS) {
111
+ const params = source.getParams(),
112
+ options = {
113
+ "url": source.getUrls()[0],
114
+ "parameters": params,
115
+ "layers": params.LAYERS,
116
+ "show": false
117
+ },
118
+ tileGrid = source.getTileGrid();
119
+
120
+ if (tileGrid) {
121
+ const ext = olLayer.getExtent();
122
+
123
+ if (ext && viewProj) {
124
+ options.rectangle = olcsCore.extentToRectangle(ext, viewProj);
125
+ const minMax = this.getMinMaxLevelFromTileGrid(tileGrid, ext, viewProj);
126
+
127
+ options.tileWidth = tileGrid.getTileSize(0)[0];
128
+ options.tileHeight = tileGrid.getTileSize(0)[1];
129
+ options.minimumLevel = minMax[0];
130
+ options.maximumLevel = minMax[1];
131
+ }
132
+ }
133
+ /* eslint-disable no-undef */
134
+ provider = new Cesium.WebMapServiceImageryProvider(options);
135
+ }
136
+ else if (source instanceof StaticImageSource) {
137
+ const extent = source.getImageExtent(),
138
+ options = {
139
+ "url": source.getUrl(),
140
+ "show": false
141
+ },
142
+ bottomLeftCorner = proj4("EPSG:25832", "EPSG:4326", getBottomLeft(extent)),
143
+ topRightCorner = proj4("EPSG:25832", "EPSG:4326", getTopRight(extent));
144
+
145
+ /* eslint-disable no-undef */
146
+ options.rectangle = Cesium.Rectangle.fromDegrees(bottomLeftCorner[0], bottomLeftCorner[1], topRightCorner[0], topRightCorner[1]);
147
+ /* eslint-disable no-undef */
148
+ provider = new Cesium.SingleTileImageryProvider(options);
149
+
150
+ }
151
+ else {
152
+ console.warn("Sources other than TileImage are currently not supported.");
153
+ return null;
154
+ }
155
+
156
+ // the provider is always non-null if we got this far
157
+ layerOptions = {
158
+ "show": false
159
+ };
160
+ /* eslint-disable no-undef */
161
+ cesiumLayer = new Cesium.ImageryLayer(provider, layerOptions);
162
+
163
+ return cesiumLayer ? [cesiumLayer] : null;
164
+ }
165
+
166
+ /**
167
+ *
168
+ * @param {ol.Extent} extent -
169
+ * @param {ol.ProjectionLike} projection -
170
+ * @return {Array.<Cesium.Cartographic>} -
171
+ * @private
172
+ */
173
+ getExtentPoints (extent, projection) {
174
+ const wgs84Extent = transformExtent(extent, projection, "EPSG:4326"),
175
+ olCoords = [
176
+ getBottomLeft(wgs84Extent),
177
+ getBottomRight(wgs84Extent),
178
+ getTopRight(wgs84Extent),
179
+ getTopLeft(wgs84Extent)
180
+ ];
181
+
182
+ /* eslint-disable no-undef */
183
+ return olCoords.map(coord => Cesium.Cartographic.fromDegrees(coord[0], coord[1]));
184
+ }
185
+ /**
186
+ *
187
+ * @param {ol.tilegrid.TileGrid} tilegrid -
188
+ * @param {ol.Extent} extent -
189
+ * @param {ol.ProjectionLike} projection -
190
+ * @return {Array.<Number>} -
191
+ */
192
+ getMinMaxLevelFromTileGrid (tilegrid, extent, projection) {
193
+ const olCoords = [
194
+ getBottomLeft(extent),
195
+ getBottomRight(extent),
196
+ getTopRight(extent),
197
+ getTopLeft(extent)
198
+ ],
199
+ resolution = tilegrid.getResolutions().slice(-1).pop(),
200
+ tileCoordsLocal = olCoords.map(position => tilegrid.getTileCoordForCoordAndResolution(position, resolution)),
201
+ distanceLocalX = Math.abs(tileCoordsLocal[0][1] - tileCoordsLocal[1][1]),
202
+ distanceLocalY = Math.abs(tileCoordsLocal[0][2] - tileCoordsLocal[3][2]),
203
+ extentCoords = this.getExtentPoints(extent, projection),
204
+ /* eslint-disable no-undef */
205
+ tilingScheme = new Cesium.GeographicTilingScheme({});
206
+ let minLevel = 0,
207
+ maxLevel = 20;
208
+
209
+ while (minLevel < maxLevel) {
210
+ /* eslint-disable no-loop-func */
211
+
212
+ const tileCoords = extentCoords.map(position => tilingScheme.positionToTileXY(position, minLevel)),
213
+ distances = [];
214
+ /* eslint-enable no-loop-func */
215
+
216
+ distances.push(Math.abs(tileCoords[0].x - tileCoords[1].x));
217
+ distances.push(Math.abs(tileCoords[0].y - tileCoords[3].y));
218
+ if (distances[0] > 1 || distances[1] > 1) {
219
+ minLevel--;
220
+ break;
221
+ }
222
+ minLevel++;
223
+ }
224
+ while (maxLevel > minLevel) {
225
+ /* eslint-disable no-loop-func */
226
+
227
+ const tileCoords = extentCoords.map(position => tilingScheme.positionToTileXY(position, maxLevel)),
228
+ distances = [];
229
+ /* eslint-enable no-loop-func */
230
+
231
+ distances.push(Math.abs(tileCoords[0].x - tileCoords[1].x));
232
+ distances.push(Math.abs(tileCoords[0].y - tileCoords[3].y));
233
+ if (distances[0] < distanceLocalX || distances[1] < distanceLocalY) {
234
+ maxLevel++;
235
+ break;
236
+ }
237
+ maxLevel--;
238
+ }
239
+ return [minLevel, maxLevel];
240
+ }
241
+
242
+ /**
243
+ * @inheritDoc
244
+ */
245
+ createSingleLayerCounterparts (olLayerWithParents) {
246
+ const olLayer = olLayerWithParents.layer,
247
+ uid = getUid(olLayer).toString(),
248
+ viewProj = this.view.getProjection(),
249
+ cesiumObjects = this.convertLayerToCesiumImageries(olLayer, viewProj);
250
+
251
+ if (cesiumObjects) {
252
+ const listenKeyArray = [];
253
+
254
+ [olLayerWithParents.layer].concat(olLayerWithParents.parents).forEach((olLayerItem) => {
255
+ listenKeyArray.push(olLayerItem.on(["change:opacity", "change:visible"], () => {
256
+ // the compiler does not seem to be able to infer this
257
+ /* eslint-disable no-console */
258
+
259
+ console.assert(cesiumObjects);
260
+ /* eslint-enable no-console */
261
+ for (let i = 0; i < cesiumObjects.length; ++i) {
262
+ olcsCore.updateCesiumLayerProperties(olLayerWithParents, cesiumObjects[i]);
263
+ }
264
+ }));
265
+ });
266
+
267
+ for (let i = 0; i < cesiumObjects.length; ++i) {
268
+ olcsCore.updateCesiumLayerProperties(olLayerWithParents, cesiumObjects[i]);
269
+ }
270
+
271
+ // there is no way to modify Cesium layer extent,
272
+ // we have to recreate when OpenLayers layer extent changes:
273
+ listenKeyArray.push(olLayer.on("change:extent", function () {
274
+ for (let i = 0; i < cesiumObjects.length; ++i) {
275
+ this.cesiumLayers.remove(cesiumObjects[i], true); // destroy
276
+ this.ourLayers.remove(cesiumObjects[i], false);
277
+ }
278
+ delete this.layerMap[getUid(olLayer)]; // invalidate the map entry
279
+ this.synchronize();
280
+ }, this));
281
+
282
+ listenKeyArray.push(olLayer.on("change", function () {
283
+ // when the source changes, re-add the layer to force update
284
+ for (let i = 0; i < cesiumObjects.length; ++i) {
285
+ const position = this.cesiumLayers.indexOf(cesiumObjects[i]);
286
+
287
+ if (position >= 0) {
288
+ this.cesiumLayers.remove(cesiumObjects[i], false);
289
+ this.cesiumLayers.add(cesiumObjects[i], position);
290
+ }
291
+ }
292
+ }.bind(this)));
293
+
294
+ this.olLayerListenKeys[uid].push(...listenKeyArray);
295
+ }
296
+
297
+ return Array.isArray(cesiumObjects) ? cesiumObjects : null;
298
+ }
299
+
300
+ /**
301
+ * Order counterparts using the same algorithm as the Openlayers renderer:
302
+ * z-index then original sequence order.
303
+ * @override
304
+ * @protected
305
+ */
306
+ orderLayers () {
307
+ const layers = [],
308
+ zIndices = {},
309
+ queue = [this.mapLayerGroup];
310
+
311
+ while (queue.length > 0) {
312
+ const olLayer = queue.splice(0, 1)[0];
313
+
314
+ layers.push(olLayer);
315
+ zIndices[getUid(olLayer)] = olLayer.getZIndex();
316
+
317
+ if (olLayer instanceof olLayerGroup) {
318
+ const sublayers = olLayer.getLayers();
319
+
320
+ if (sublayers) {
321
+ // Prepend queue with sublayers in order
322
+ queue.unshift(...sublayers.getArray());
323
+ }
324
+ }
325
+ }
326
+
327
+ stableSort(layers, (layer1, layer2) => zIndices[getUid(layer1)] - zIndices[getUid(layer2)]);
328
+
329
+ layers.forEach(function (olLayer) {
330
+ const olLayerId = getUid(olLayer).toString(),
331
+ cesiumObjects = this.layerMap[olLayerId];
332
+
333
+ if (cesiumObjects) {
334
+ cesiumObjects.forEach(this.raiseToTop, this);
335
+ }
336
+ }, this);
337
+ }
338
+
339
+ /**
340
+ * @param {Cesium.ImageryLayer} counterpart -
341
+ * @returns {void}
342
+ */
343
+ raiseToTop (counterpart) {
344
+ this.cesiumLayers.raiseToTop(counterpart);
345
+ }
346
+ }
347
+
348
+ export default WMSRasterSynchronizer;