Get the closest Feature in a FeatureCollection against a given Feature
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 {object} Feature
* @param {object} FeatureCollection
* @returns {(object|null)} Feature Properties or null if nothing found or malformed reference
*/
function getClosestFeature (Feature, FeatureCollection) {
if (!isPointFeature(Feature)) {
console.error('The Feature of reference is malformed.');
return null;
}
const lat1 = Feature.geometry.coordinates[1];
const lng1 = Feature.geometry.coordinates[0];
const radLat1 = Math.PI * lat1 / 180;
const nauticalMileToMile = Math.PI * 60 * 1.1515;
let lowestValue = 12451; // Earth average longest semicircle
let closestPlace = null;
for (const i in FeatureCollection.features) {
const thisFeature = FeatureCollection.features[i];
if (!isPointFeature(thisFeature)) {
continue;
}
const lng2 = thisFeature.geometry.coordinates[0];
const lat2 = thisFeature.geometry.coordinates[1];
const placeMeta = thisFeature.properties;
const radLat2 = Math.PI * lat2 / 180;
const theta = lng1 - lng2;
const radTheta = Math.PI * theta / 180;
let dist = Math.sin(radLat1) * Math.sin(radLat2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.cos(radTheta);
dist = Math.acos(dist) * 180 / nauticalMileToMile;
if (dist < lowestValue) {
lowestValue = dist;
closestPlace = placeMeta;
}
}
return closestPlace;
}