demarches-normaliennes/app/javascript/components/shared/maplibre/utils.ts
2022-03-17 11:55:20 +01:00

89 lines
2.4 KiB
TypeScript

import type { LngLat, LngLatLike, LngLatBoundsLike } from 'maplibre-gl';
import type { Geometry, FeatureCollection, Feature } from 'geojson';
import { LngLatBounds } from 'maplibre-gl';
import invariant from 'tiny-invariant';
export function getBounds(geometry: Geometry): LngLatBoundsLike {
const bbox = new LngLatBounds();
if (geometry.type === 'Point') {
return [geometry.coordinates, geometry.coordinates] as [
[number, number],
[number, number]
];
} else if (geometry.type === 'LineString') {
for (const coordinate of geometry.coordinates) {
bbox.extend(coordinate as [number, number]);
}
} else {
invariant(
geometry.type != 'GeometryCollection',
'GeometryCollection not supported'
);
for (const coordinate of geometry.coordinates[0]) {
bbox.extend(coordinate as [number, number]);
}
}
return bbox;
}
export function findFeature<G extends Geometry>(
featureCollection: FeatureCollection<G>,
value: unknown,
property = 'id'
): Feature<G> | null {
return (
featureCollection.features.find(
(feature) => feature.properties && feature.properties[property] === value
) ?? null
);
}
export function filterFeatureCollection<G extends Geometry>(
featureCollection: FeatureCollection<G>,
source: string
): FeatureCollection<G> {
return {
type: 'FeatureCollection',
features: featureCollection.features.filter(
(feature) => feature.properties?.source === source
)
};
}
export function filterFeatureCollectionByGeometryType<G extends Geometry>(
featureCollection: FeatureCollection<G>,
type: Geometry['type']
): FeatureCollection<G> {
return {
type: 'FeatureCollection',
features: featureCollection.features.filter(
(feature) => feature.geometry.type === type
)
};
}
export function generateId(): string {
return Math.random().toString(20).substring(2, 6);
}
export function getCenter(geometry: Geometry, lngLat: LngLat): LngLatLike {
const bbox = new LngLatBounds();
invariant(
geometry.type != 'GeometryCollection',
'GeometryCollection not supported'
);
switch (geometry.type) {
case 'Point':
return [...geometry.coordinates] as [number, number];
case 'LineString':
return [lngLat.lng, lngLat.lat];
default:
for (const coordinate of geometry.coordinates[0]) {
bbox.extend(coordinate as [number, number]);
}
return bbox.getCenter();
}
}