This script returns the properties
of the closest Feature
in a FeatureCollection
against a given Feature
(GeoJSON RFC7946).
/**
* @param Feature with type `Point`
* @returns {boolean}
*/
function isPointFeature (feature) {
return feature.type === 'Feature' && feature.geometry.type === 'Point';
}
/**
* @param degrees
* @returns {number}
*/
function toRadians (degrees) {
return degrees * Math.PI / 180;
}
/**
* @param {object} Feature
* @param {object} FeatureCollection
* @returns {(object|null)} Feature Properties or null if nothing found or malformed reference
*/
function getClosestFeature (referenceFeature, featureCollection) {
if (!isPointFeature(referenceFeature)) {
console.error('The reference feature is malformed.');
return null;
}
const {coordinates: [lng1, lat1]} = referenceFeature.geometry;
const earthRadiusKm = 6371; // Radius of the Earth in kilometers
let closestDistance = Infinity;
let closestPlace = null;
featureCollection.features.forEach((feature) => {
if (!isPointFeature(feature)) return;
const {coordinates: [lng2, lat2], properties} = feature.geometry;
const dLat = toRadians(lat2 - lat1);
const dLng = toRadians(lng2 - lng1);
const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(toRadians(lat1)) * Math.cos(toRadians(lat2)) * Math.sin(dLng / 2) * Math.sin(dLng / 2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
const distance = earthRadiusKm * c;
if (distance < closestDistance) {
closestDistance = distance;
closestPlace = properties;
}
});
return closestPlace;
}
Keep in mind that this code assumes a spherical Earth, and the Haversine formula provides an approximation of distances between two points on a sphere. If high accuracy is needed, more sophisticated distance calculations considering the Earth’s ellipsoidal shape may be required.