Source: mixins/ol-map-layers.js

/**
 * @desc A mixin object containing methods related to map layers
 * @module MapLayersMixin
 */
import { OSM, BingMaps } from 'ol/source';
import { transform } from "ol/proj";
import { GeoTIFF as GeoTIFFSource } from 'ol/source';
import { get as getProjection, useGeographic } from 'ol/proj';
export const MapLayersMixin = {
    methods: {

        /**
         * Sets the base layer of the map based on the selectedBaseLayer value.
         * If selectedBaseLayer is 1, sets the base layer source to OpenStreetMap (OSM).
         * If selectedBaseLayer is not 1, sets the base layer source to Bing Maps with the specified key and imagerySet.
         * Updates the map size and forces a component update.
         * @async
         * @returns {Promise<void>}
         */
        async setBaseLayer() {
            if (this.selectedBaseLayer.value == 1) {
                this.baseLayer.setSource(new OSM());
            } else {
                this.baseLayer.setSource(new BingMaps({
                    key: 'AnNHHAjCQ3arTU0FoTUB1zoCdKC2png2M2pstqoV5uFhCHorOx_aUz1Yt8RA6Xly',
                    imagerySet: 'AerialWithLabels',
                }));
            }
            this.baseLayer.getSource().changed();
            this.map.updateSize();
            this.$forceUpdate();
        },

        /**
         * Clears the shape source and adds features to it based on the selected shape.
         * @async
         * @function setShapeLayer
         * @memberof module:mixins/ol-map-layers
         * @returns {Promise<void>} A promise that resolves when the shape layer is set.
         */
        async setShapeLayer() {
            this.shapeSource.clear();
            if (this.selectedShape) {
                let ret = await this.get("Common/GetShape", {
                    Id: this.selectedShape.value,
                    Srid: this.srid
                });
                if (ret && ret.features) {
                    let features = this.format.readFeatures(ret);
                    this.shapeSource.addFeatures(features);
                    this.animateToExtent(this.shapeSource);
                }
            }
        },

        /**
         * Creates a point collection feature from the given data.
         *
         * @param {Object} data - The data used to create the point collection.
         * @param {string} projection - The projection used for transforming coordinates.
         * @returns {Object} - The created point collection feature.
         */
        createPointCollection(data, projection) {
            var featureCollection = {
                type: 'FeatureCollection',
                features: data.data.map(function(row) {
                    return {
                        type: 'Feature',
                        geometry: {
                            type: 'Point',
                            coordinates: transform([row[0], row[1]], 'EPSG:4326', projection)
                        },
                        properties: {
                            value: row[2],
                            date: row[3],
                            color_code: row[4] ?? '#ff0000',
                            name: row[8] || row[5],
                            nuts_0: row[6],
                            description: row[7],
                            point_id: row[9],
                            sample: row[10],
                            has_spectrum: row[11]
                        },
                    };
                })
            };  
            return featureCollection;
        },

        /**
         * Sets the point layer on the map.
         * @async
         * @returns {Promise<void>} A promise that resolves when the point layer is set.
         */
        async setPointLayer() {
            this.pointSource.clear();
            this.pointFeatures = [];
            if (!this.showPoints) return;
            if (!this.selectedIndicator) {
                return;
            } else {
                this.$store.working = true;
                let data = await this.get("Home/GetIndicatorValues", { indicatorId: this.selectedIndicator.value, dataSourceId: this.selectedDataSource ? this.selectedDataSource.value : null });
                let pointCollection = this.createPointCollection(data, this.projection);
                this.pointFeatures = this.format.readFeatures(pointCollection);

                this.pointSource.addFeatures(this.pointFeatures);
                this.pointLayer.setSource(this.clustered ? this.clusteredSource : this.pointSource);
                //this.pointLayer.setVisible(true);
                this.animateToExtent(this.pointSource);
                this.$store.working = false;
            }
        },
        
        /**
         * Sets the tile layer containig GeoTiff sources for the map.
         * @async
         * @returns {Promise<void>} A promise that resolves when the tile layer is set.
         */
        async setTileLayer() {
            this.$store.working = true;
            //useGeographic();
            // create appropriate source
            if (this.selectedCatalog) {
                let source;
                source = new GeoTIFFSource({
                    normalize: false,
                    sources: [{ url: this.selectedCatalog.source },
                    ],
                    //nodata: this.selectedTitle.no_data,
                    projection: getProjection("EPSG:" + this.selectedTitle.srid),
                });
                source.on("change", () => {
                    if (source.getState() === "error") {
                        this.showError(this.$t("Error loading GeoTIFF") + ": " + source.getError());
                        return;
                    }
                });
                this.tiffLayer.setSource(source);
                this.tiffLayer.setStyle({
                    color: JSON.parse(this.selectedTitle.color_map)
                });
                //['interpolate', ['linear'], ['band', 1],
                //     0, [255, 255, 255, 0], 60, [0, 0, 255], 120, [0, 255, 0]]
                //color: ['case', ['==', ['band', 1], 0], [0, 0, 255, 0], ['<=', ['band', 1], 50], [255, 0, 0], [0, 0, 255]]
                //});
                this.tiffLayer.changed();
                this.tiffLayer.setVisible(true);
            } else {
                this.tiffLayer.setSource(null);
                this.tiffLayer.setVisible(false);
                // this.map.getLayers().getArray().find(x => x.get("type") == 'GeoTIFF').setVisible(false);
            }
            this.$store.working = false;
        },

        /**
         * Sets the boundaries layer on the map based on the selected NUTS level.
         * If the NUTS level is greater than or equal to 0, it makes an asynchronous request to retrieve the boundaries data.
         * The retrieved data is then added to the boundaries source of the map.
         * If the NUTS level is less than 0, the boundaries source is cleared.
         * @returns {Promise<void>} A promise that resolves when the boundaries layer is set.
         */
        async setBoundariesLayer() {
            if (this.nutsLevel && this.nutsLevel.value >= 0) {
                this.$store.working = true;
                let featureCollection = await this.get("Home/GetBoundaries", {
                    level: this.nutsLevel.value, srid: this.srid, zoom: Math.round(this.zoom), extent: this.extent.join(","), indicatorId: this.selectedIndicator ? this.selectedIndicator.value : null, dataSourceId: this.selectedDataSource ? this.selectedDataSource.value : null
                });
                this.boundariesSource.clear();
                if (featureCollection.features) {
                    this.boundariesSource.addFeatures(this.format.readFeatures(featureCollection));
                }
                this.$store.working = false;
            } else {
                this.boundariesSource.clear();
            }
        },
    },
}