Поиск объектов в радиусе в геопространственных задачах опирается на вычисление расстояний на поверхности Земли и проверку принадлежности точек заданной области. В Turf.js этот функционал реализуется через набор геометрических примитивов и пространственных операций, позволяющих строить запросы «вокруг точки» без использования серверных ГИС-систем.
Радиусный поиск в геоинформационных системах формализуется через множество точек, удовлетворяющих условию:
В геодезическом контексте расстояние вычисляется не в декартовой плоскости, а по поверхности эллипсоида или сферы, что критично для корректности результатов на больших расстояниях.
В Turf.js основой является работа с GeoJSON-объектами:
Point — координатная точкаFeature<Point> — точка с метаданнымиPolygon и Circle — области поискаFeatureCollection — набор объектовКлючевой примитив для радиусного поиска — расстояние между двумя точками:
import distance from "@turf/distance";
const from = [76.8865, 43.2389];
const to = [76.9456, 43.2551];
const result = distance(from, to, { units: "kilometers" });
Функция учитывает кривизну Земли и возвращает расстояние в заданных единицах:
Формально операция опирается на сферическую модель и формулу гаверсинусов, что обеспечивает приемлемую точность для большинства прикладных задач.
Одним из базовых способов реализации поиска в радиусе выступает построение геометрического круга:
import circle from "@turf/circle";
const center = [76.8865, 43.2389];
const radius = 5;
const options = {
steps: 64,
units: "kilometers"
};
const circlePolygon = circle(center, radius, options);
Полученный полигон представляет приближение окружности на сфере. Чем
больше значение steps, тем выше точность аппроксимации.
Дальнейшая операция поиска сводится к проверке принадлежности точек этому полигону.
После построения области выполняется пространственная проверка:
import booleanPointInPolygon from "@turf/boolean-point-in-polygon";
const points = [
[76.88, 43.23],
[76.90, 43.25],
[76.95, 43.27]
];
const within = points.filter((pt) =>
booleanPointInPolygon(pt, circlePolygon)
);
Механизм основан на алгоритме ray casting, определяющем принадлежность точки полигону через пересечение луча с границами фигуры.
Буферизация геометрии представляет более универсальный метод построения радиуса:
import buffer from "@turf/buffer";
const center = {
type: "Feature",
geometry: {
type: "Point",
coordinates: [76.8865, 43.2389]
}
};
const buffered = buffer(center, 5, { units: "kilometers" });
Буфер создаёт полигон вокруг точки, эквидистантный на заданное
расстояние. В отличие от circle, буфер может применяться к
линиям и полигонам, расширяя сценарии использования.
Проверка попадания выполняется аналогично:
import pointsWithinPolygon from "@turf/points-within-polygon";
const result = pointsWithinPolygon(featureCollectionOfPoints, buffered);
Наиболее прямолинейный метод — фильтрация точек по расстоянию без построения полигонов:
import distance from "@turf/distance";
const center = [76.8865, 43.2389];
const filtered = points.filter((point) => {
const d = distance(center, point, { units: "kilometers" });
return d <= 5;
});
Данный подход используется при небольших объёмах данных или при предварительной фильтрации перед более сложной пространственной обработкой.
При увеличении количества объектов линейный перебор становится вычислительно затратным. В практических системах применяется предварительная фильтрация по bounding box:
Пример подготовки ограничивающего прямоугольника:
import bbox from "@turf/bbox";
const box = bbox(circlePolygon);
Дальнейшая проверка выполняется перед точным вычислением расстояния.
Дополнительно используются пространственные индексы (например, R-tree через сторонние библиотеки), позволяющие уменьшить сложность поиска с O(n) до O(log n).
Все операции радиусного поиска зависят от параметра
units. Несоответствие единиц приводит к систематическим
ошибкам:
Геодезические вычисления в Turf.js используют сферическую модель, что создаёт погрешность, возрастающую с увеличением радиуса. Для малых расстояний (до 10–20 км) отклонения минимальны, но на глобальных масштабах требуется учитывать эллипсоидальные модели через внешние библиотеки.
В реальных задачах радиусный поиск редко используется изолированно. Типичная цепочка обработки включает:
distancebooleanPointInPolygonFeatureCollectionПример комбинированного подхода:
import distance from "@turf/distance";
import booleanPointInPolygon from "@turf/boolean-point-in-polygon";
import circle from "@turf/circle";
const center = [76.8865, 43.2389];
const searchArea = circle(center, 3, { units: "kilometers", steps: 64 });
const result = points.filter((p) => {
if (!booleanPointInPolygon(p, searchArea)) return false;
return distance(center, p, { units: "kilometers" }) <= 3;
});
Такой подход снижает количество дорогостоящих операций расстояния и повышает стабильность результатов.
Радиусные запросы в геоаналитике используются в задачах:
В системах реального времени радиусный поиск часто является базовым слоем поверх потоковой обработки координат, где каждая точка проходит через серию пространственных фильтров.
Радиусный поиск в Turf.js основан на предположении о гладкой поверхности Земли. Это приводит к следующим особенностям:
При работе вблизи полюсов и через 180-й меридиан требуется учитывать разрыв геометрии и корректно нормализовать координаты.
GeoJSON остаётся основной структурой передачи данных. При этом производительность зависит от:
FeatureCollectionОптимизация достигается за счёт:
circle и
bufferdistanceПри масштабировании до сотен тысяч точек радиусный поиск становится многоуровневой системой фильтров, где Turf.js выполняет роль геометрического ядра вычислений.