/**
* @module
*/
import olLayerGroup from 'ol/layer/Group';
import googAsserts from 'goog/asserts';
import olArray from 'ol/array';
import olBase from 'ol';
import olcsAbstractSynchronizer from './AbstractSynchronizer.js';
import olcsCore from './core.js';
const exports = function(map, scene) {
/**
* @type {!Cesium.ImageryLayerCollection}
* @private
*/
this.cesiumLayers_ = scene.imageryLayers;
/**
* @type {!Cesium.ImageryLayerCollection}
* @private
*/
this.ourLayers_ = new Cesium.ImageryLayerCollection();
olcsAbstractSynchronizer.call(this, map, scene);
};
olBase.inherits(exports, olcsAbstractSynchronizer);
/**
* @inheritDoc
*/
exports.prototype.addCesiumObject = function(object) {
this.cesiumLayers_.add(object);
this.ourLayers_.add(object);
};
/**
* @inheritDoc
*/
exports.prototype.destroyCesiumObject = function(object) {
object.destroy();
};
/**
* @inheritDoc
*/
exports.prototype.removeSingleCesiumObject = function(object, destroy) {
this.cesiumLayers_.remove(object, destroy);
this.ourLayers_.remove(object, false);
};
/**
* @inheritDoc
*/
exports.prototype.removeAllCesiumObjects = function(destroy) {
for (let i = 0; i < this.ourLayers_.length; ++i) {
this.cesiumLayers_.remove(this.ourLayers_.get(i), destroy);
}
this.ourLayers_.removeAll(false);
};
/**
* Creates an array of Cesium.ImageryLayer.
* May be overriden by child classes to implement custom behavior.
* The default implementation handles tiled imageries in EPSG:4326 or
* EPSG:3859.
* @param {!ol.layer.Base} olLayer
* @param {?ol.proj.Projection} viewProj Projection of the view.
* @return {?Array.<!Cesium.ImageryLayer>} array or null if not possible
* (or supported)
* @protected
*/
exports.prototype.convertLayerToCesiumImageries = function(olLayer, viewProj) {
const result = olcsCore.tileLayerToImageryLayer(olLayer, viewProj);
return result ? [result] : null;
};
/**
* @inheritDoc
*/
exports.prototype.createSingleLayerCounterparts = function(olLayerWithParents) {
const olLayer = olLayerWithParents.layer;
const uid = olBase.getUid(olLayer).toString();
const viewProj = this.view.getProjection();
const cesiumObjects = this.convertLayerToCesiumImageries(olLayer, viewProj);
if (cesiumObjects) {
const listenKeyArray = [];
[olLayerWithParents.layer].concat(olLayerWithParents.parents).forEach((olLayerItem) => {
listenKeyArray.push(olLayerItem.on(['change:opacity', 'change:visible'], () => {
// the compiler does not seem to be able to infer this
googAsserts.assert(cesiumObjects);
for (let i = 0; i < cesiumObjects.length; ++i) {
olcsCore.updateCesiumLayerProperties(olLayerWithParents, cesiumObjects[i]);
}
}));
});
for (let i = 0; i < cesiumObjects.length; ++i) {
olcsCore.updateCesiumLayerProperties(olLayerWithParents, cesiumObjects[i]);
}
// there is no way to modify Cesium layer extent,
// we have to recreate when OpenLayers layer extent changes:
listenKeyArray.push(olLayer.on('change:extent', function(e) {
for (let i = 0; i < cesiumObjects.length; ++i) {
this.cesiumLayers_.remove(cesiumObjects[i], true); // destroy
this.ourLayers_.remove(cesiumObjects[i], false);
}
delete this.layerMap[olBase.getUid(olLayer)]; // invalidate the map entry
this.synchronize();
}, this));
listenKeyArray.push(olLayer.on('change', function(e) {
// when the source changes, re-add the layer to force update
for (let i = 0; i < cesiumObjects.length; ++i) {
const position = this.cesiumLayers_.indexOf(cesiumObjects[i]);
if (position >= 0) {
this.cesiumLayers_.remove(cesiumObjects[i], false);
this.cesiumLayers_.add(cesiumObjects[i], position);
}
}
}, this));
this.olLayerListenKeys[uid].push(...listenKeyArray);
}
return Array.isArray(cesiumObjects) ? cesiumObjects : null;
};
/**
* Order counterparts using the same algorithm as the Openlayers renderer:
* z-index then original sequence order.
* @override
* @protected
*/
exports.prototype.orderLayers = function() {
const layers = [];
const zIndices = {};
const queue = [this.mapLayerGroup];
while (queue.length > 0) {
const olLayer = queue.splice(0, 1)[0];
layers.push(olLayer);
zIndices[olBase.getUid(olLayer)] = olLayer.getZIndex();
if (olLayer instanceof olLayerGroup) {
const sublayers = olLayer.getLayers();
if (sublayers) {
// Prepend queue with sublayers in order
queue.unshift(...sublayers.getArray());
}
}
}
olArray.stableSort(layers, (layer1, layer2) =>
zIndices[olBase.getUid(layer1)] - zIndices[olBase.getUid(layer2)]
);
layers.forEach(function(olLayer) {
const olLayerId = olBase.getUid(olLayer).toString();
const cesiumObjects = this.layerMap[olLayerId];
if (cesiumObjects) {
cesiumObjects.forEach(this.raiseToTop, this);
}
}, this);
};
/**
* @param {Cesium.ImageryLayer} counterpart
*/
exports.prototype.raiseToTop = function(counterpart) {
this.cesiumLayers_.raiseToTop(counterpart);
};
export default exports;