mobility-toolbox-js
Version:
Toolbox for JavaScript applications in the domains of mobility and logistics.
128 lines (127 loc) • 5.92 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
import { getUid } from 'ol';
import GeoJSON from 'ol/format/GeoJSON';
import { getLayersAsFlatArray } from '../../common';
/**
* @private
*/
const format = new GeoJSON();
/**
* @private
*/
const getFeaturesFromWMS = (source, options, abortController) => {
let url;
const { coordinate, params, projection, resolution } = options;
if (source && resolution && projection) {
url = source.getFeatureInfoUrl(coordinate, resolution, projection, Object.assign({ info_format: 'application/json', query_layers: source.getParams().layers }, params));
}
// @ts-expect-error url can be undefined
return fetch(url, { signal: abortController.signal })
.then((resp) => {
return resp.json();
})
.then((featureCollection) => {
return format.readFeatures(featureCollection);
})
.catch(() => {
return [];
});
};
/**
* @private
*/
let abortControllers = {};
/**
* Fetches feature information at a given coordinate from the provided layers.
* It supports WMS sources and MapLibre layers and custom layer via the method `layer.getFeatureInfoAtCoordinate`.
*
* @param {Coordinate} coordinate - The coordinate to query for feature information.
* @param {ol/layer/BaseLayer~BaseLayer[]} layers - The layers to query for feature information.
* @param {number} hitTolerance - The pixel tolerance for feature selection.
* @param {boolean} ignoreLayerMethod - If true, it ignores the `getFeatureInfoAtCoordinate` method on layers.
* @returns {LayerGetFeatureInfoResponse[]} A promise that resolves to an array of feature information responses.
* @private
*/
const getFeatureInfoAtCoordinate = (coordinate_1, layers_1, ...args_1) => __awaiter(void 0, [coordinate_1, layers_1, ...args_1], void 0, function* (coordinate, layers, hitTolerance = 5, ignoreLayerMethod = false) {
// Kill all previous requests
Object.values(abortControllers).forEach((abortController) => {
abortController === null || abortController === void 0 ? void 0 : abortController.abort();
});
abortControllers = {};
const flatLayers = getLayersAsFlatArray(layers);
const promises = flatLayers.map((baseLayer) => __awaiter(void 0, void 0, void 0, function* () {
var _a, _b, _c, _d;
const map = baseLayer.getMapInternal();
const projection = (_b = (_a = map === null || map === void 0 ? void 0 : map.getView()) === null || _a === void 0 ? void 0 : _a.getProjection()) === null || _b === void 0 ? void 0 : _b.getCode();
const emptyResponse = {
coordinate,
features: [],
layer: baseLayer,
};
if (!projection) {
return Promise.resolve(emptyResponse);
}
const layer = baseLayer;
// For backward compatibility
// @ts-expect-error getFeatureInfoAtCoordinate is deprecated
if (!ignoreLayerMethod && layer.getFeatureInfoAtCoordinate) {
// @ts-expect-error getFeatureInfoAtCoordinate is deprecated
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
return layer.getFeatureInfoAtCoordinate(coordinate);
}
// WMS sources
// Here we don't use instanceof, to be able to use this function if a layer comes from 2 different ol versions.
const source = layer === null || layer === void 0 ? void 0 : layer.getSource();
if (source === null || source === void 0 ? void 0 : source.getFeatureInfoUrl) {
const id = getUid(layer);
// Abort and recreates one controller per layer
(_c = abortControllers[id]) === null || _c === void 0 ? void 0 : _c.abort();
abortControllers[id] = new AbortController();
const resolution = (_d = map === null || map === void 0 ? void 0 : map.getView()) === null || _d === void 0 ? void 0 : _d.getResolution();
const features = yield getFeaturesFromWMS(source, {
coordinate,
params: {
info_format: 'application/json',
query_layers: source.getParams().layers,
},
projection,
resolution,
}, abortControllers[id]).catch(() => {
return [];
});
const featureInfoResponse = {
coordinate,
features,
layer,
};
return Promise.resolve(featureInfoResponse);
}
// Other layers
// For last resort we try the map function to get the features from the map
const pixel = map === null || map === void 0 ? void 0 : map.getPixelFromCoordinate(coordinate);
if (!pixel) {
return Promise.resolve(emptyResponse);
}
const features = map === null || map === void 0 ? void 0 : map.getFeaturesAtPixel(pixel, {
hitTolerance: layer.get('hitTolerance') || hitTolerance || 5,
layerFilter: (l) => {
return l === layer;
},
});
return Promise.resolve({
coordinate,
features,
layer,
});
}));
return Promise.all(promises);
});
export default getFeatureInfoAtCoordinate;