@geogirafe/lib-geoportal
Version:
GeoGirafe is a flexible application to build online geoportals.
118 lines (117 loc) • 4.68 kB
JavaScript
import { fromCircle } from 'ol/geom/Polygon.js';
import { get as getProjection } from 'ol/proj';
import { getDistance as getSphericalDistance, getArea as getSphericalArea } from 'ol/sphere';
import { unByKey } from 'ol/Observable';
import { LineString } from 'ol/geom';
import GeoConsts from '../geoconsts';
import StateManager from '../state/statemanager';
import { buffer } from 'ol/extent';
/**
* Unsubscribe to all OpenLayer listeners.
*/
export const unByKeyAll = (eventKeys) => {
eventKeys.forEach((eventKey) => unByKey(eventKey));
};
/**
* @returns a layer in the map that match the given name (property name).
*/
export const getOlayerByName = (map, layerName) => {
return map.getAllLayers().find((layer) => layer.get('name') === layerName);
};
/**
* Clone the properties of the given feature and delete ol properties to keep only the feature "app" properties.
* Handle map server values served as object and serve them as "simple" values.
*/
export const removeUnwantedOlParams = (feature, keepGeom = false) => {
const properties = { ...feature.getProperties() };
delete properties.boundedBy;
if (!keepGeom) {
delete properties[feature.getGeometryName()];
}
// Handle map server values served as object.
Object.keys(properties).forEach((key) => {
const value = properties[key];
if (typeof value === 'object') {
if (value['xsi:nil'] === 'true') {
properties[key] = undefined;
}
else if (value['_content_']) {
properties[key] = value['_content_'];
}
}
});
return properties;
};
/**
* @returns A polygon generated from the circle.
*/
export const polygonFromCircle = (geometry) => {
return fromCircle(geometry, GeoConsts.CIRCLE_TO_POLYGON_SIDES);
};
/**
* @param coordinates ol Coordinate list
* @returns the length between coordinates, considering the current map projection (projected or geographic)
*/
export const getDistance = (coordinates) => {
if (isProjectionInDegrees()) {
let totalLength = 0;
coordinates.forEach((coordinate, idx) => {
if (coordinates[idx + 1]) {
totalLength += getSphericalDistance(coordinate, coordinates[idx + 1]);
}
});
return totalLength;
}
return new LineString(coordinates).getLength();
};
/**
* @param polygon ol Polygon
* @returns the area of a polygon, considering the current map projection (projected or geographic)
*/
export const getArea = (polygon) => {
if (isProjectionInDegrees()) {
return getSphericalArea(polygon, { projection: getProjection(StateManager.getInstance().state.projection) });
}
return polygon.getArea();
};
export const isProjectionInDegrees = () => {
const projection = getProjection(StateManager.getInstance().state.projection);
return projection?.getUnits() === 'degrees';
};
export const isCoordinateInDegrees = (coordinate) => {
return coordinate[0] > -90 && coordinate[0] < 90 && coordinate[1] > -180 && coordinate[1] < 180;
};
export const getSelectionBoxFromMapClick = (eventCoordinate, olMap, pixelTolerance) => {
const pointExtent = [...eventCoordinate, ...eventCoordinate];
const pixelExtent = buffer(pointExtent, pixelTolerance);
const mapExtent = [
...olMap.getCoordinateFromPixel([pixelExtent[0], pixelExtent[1]]),
...olMap.getCoordinateFromPixel([pixelExtent[2], pixelExtent[3]])
];
// Because the pixel origin is in the top left corner and the coordinate origin (in projected crs) is in the lower
// left corner, the extent is switched to [xmin, ymin, xmax, ymax]
return [
Math.min(mapExtent[0], mapExtent[2]),
Math.min(mapExtent[1], mapExtent[3]),
Math.max(mapExtent[0], mapExtent[2]),
Math.max(mapExtent[1], mapExtent[3])
];
};
export const reprojectGeometry = (geometry, sourceProjection, destinationProjection) => {
try {
if (typeof sourceProjection === 'string') {
sourceProjection = getProjection(sourceProjection) ?? undefined;
}
if (typeof destinationProjection === 'string') {
destinationProjection = getProjection(destinationProjection) ?? undefined;
}
if (!sourceProjection || !destinationProjection) {
throw new Error(`Not able to reproject geometry, invalid or unknown projection used.`);
}
const reprojectedGeometry = geometry.clone();
return reprojectedGeometry.transform(sourceProjection, destinationProjection);
}
catch (e) {
throw new Error(`Not able to reproject geometry: ${e}`);
}
};