/**
* @module meteoJS/synview/map/ol
*/
import SynviewMap from '../SynviewMap.js';
import LayerGroup from 'ol/layer/Group';
import { transform, fromLonLat } from 'ol/proj';
/**
* Name of mercator projection in openlayers
*
* @constant {string}
*/
export const projmerc = 'EPSG:3857';
/**
* Name of wgs84 projection in openlayers (lat/lon in degrees)
*
* @constant {string}
*/
export const projwgs84 = 'EPSG:4326';
/**
* Object to "communicate" with openlayers.
*
* @extends module:meteoJS/synview/map.SynviewMap
*/
export class MapOL extends SynviewMap {
constructor(options) {
super(options);
// Normalize options
if (this.options.layerGroup === undefined) {
this.options.layerGroup = new LayerGroup();
this.options.map.addLayer(this.options.layerGroup);
}
// Listen to view changes.
this.options.map.getView().on('change:center', (function () {
this.trigger('change:view', this);
}).bind(this));
this.options.map.getView().on('change:resolution', (function () {
this.trigger('change:view', this);
}).bind(this));
this.options.map.on('pointermove', (function (e) {
this.trigger('move:pointer', e);
}).bind(this));
this.options.map.on('click', (function (e) {
this.trigger('click:pointer', e);
}).bind(this));
this.options.map.on('singleclick', (function (e) {
this.trigger('singleclick:pointer', e);
}).bind(this));
this.options.map.on('dblclick', (function (e) {
this.trigger('dblclick:pointer', e);
}).bind(this));
this.options.map.on('pointerdrag', (function (e) {
this.trigger('drag:pointer', e);
}).bind(this));
}
/**
* Helper function. Returns the view center in WGS84 coordinates, lat/lon.
*
* @return {number[]} Center.
*/
getViewCenter() {
return transform(
this.options.map.getView().getCenter(),
this.options.map.getView().getProjection(),
projwgs84
);
}
/**
* Helper function. Sets the view center in WGS84 coordinates, lat/lon.
*
* @param {number[]} center Center.
* @return {module:meteoJS/synview/map/ol~MapOL} This.
*/
setViewCenter(center) {
var valid = true;
center = center.map(function (a) {
if (isNaN(a)) {
valid = false;
return undefined;
}
else
return a*1;
});
if (valid)
this.options.map.getView().setCenter(fromLonLat(center));
return this;
}
/**
* Helper function. Returns the view zoom level.
*
* @return {number|undefined} Zoom level.
*/
getViewZoom() {
return this.options.map.getView().getZoom();
}
/**
* Helper function. Sets the view zoom level.
*
* @param {number|undefined} zoom Zoom level.
* @returns {module:meteoJS/synview/map/ol~MapOL} This.
*/
setViewZoom(zoom) {
if (!isNaN(zoom))
this.options.map.getView().setZoom(zoom*1);
return this;
}
/**
* Returns a new layer group, already added to the map.
*
* @returns {external:ol/layer/Group~LayerGroup} New layer group.
*/
makeLayerGroup() {
var group = new LayerGroup();
this.options.layerGroup.getLayers().push(group);
return group;
}
/**
* Returns an event object, that is extended by several keys.
* Synview internal method.
*
* @param {external:ol/MapBrowserPointerEvent} event Map event object.
* @param {module:meteoJS/synview/typeCollection.TypeCollection} collection Type collection.
* @returns {module:meteoJS/synview/map~extendedEvent} Event object.
*/
getExtendedEventByTypeCollection(event, collection) {
event = super.getExtendedEventByTypeCollection(event, collection);
let visibleTypes = new Map();
collection.getVisibleTypes()
.filter(type => { return type.getTooltip() !== undefined; })
.map(type => visibleTypes.set(type, []));
let visibleLayers = new Set();
let visibleLayerClassnames = new Set();
for (let type of visibleTypes.keys()) {
type.getLayerGroup().getLayers().getArray()
.filter(layer => layer.getVisible())
.forEach(layer => {
visibleTypes.get(type).push(layer);
visibleLayers.add(layer);
visibleLayerClassnames.add(layer.getClassName());
});
}
this.options.map.forEachFeatureAtPixel(event.pixel, (feature, layer) => {
for (let type of visibleTypes.keys()) {
visibleTypes.get(type).forEach(l => {
if (event.synviewType !== undefined)
return;
if (l === layer) {
event.feature = feature;
event.layer = layer;
event.synviewType = type;
}
});
if (event.synviewType !== undefined)
break;
}
return event.synviewType !== undefined;
}, {
hitTolerance: 5,
layerFilter: layer => visibleLayers.has(layer)
});
if (event.feature === undefined) {
this.options.map.forEachLayerAtPixel(event.pixel, (layer, color) => {
if (color == null || color.length < 1)
return false;
for (let type of visibleTypes.keys()) {
visibleTypes.get(type).forEach(l => {
if (event.synviewType !== undefined)
return;
if (l.getClassName() == layer.getClassName()) {
event.color = color;
event.layer = layer;
event.synviewType = type;
}
});
if (event.synviewType !== undefined)
break;
}
return event.synviewType !== undefined;
}, {
hitTolerance: 5,
layerFilter: layer => visibleLayerClassnames.has(layer.getClassName())
});
}
return event;
}
/**
* Returns index of the passed layer inside the layer group of the passed type.
* Synview internal method.
*
* @param {external:ol/layer/Layer~Layer} layer Layer object.
* @param {module:meteoJS/synview/type.Type} type Type.
* @return {integer} Index.
*/
findLayerInType(layer, type) {
return type.getLayerGroup().getLayers().getArray().findIndex(function (l) {
return l == layer;
}) > -1;
}
}
export default MapOL;