Turf.js работает поверх стандарта GeoJSON и предоставляет набор алгоритмов для обработки геометрий, включая построение, преобразование и анализ пространственных объектов. Создание полигонов из набора точек является одной из базовых операций, которая встречается при обработке кластеров координат, восстановлении границ объектов, построении зон покрытия и анализе распределения данных.
Полигон в GeoJSON задаётся как массив координатных колец:
Формат:
{
"type": "Polygon",
"coordinates": [
[
[lng, lat],
[lng, lat],
[lng, lat],
[lng, lat]
]
]
}
Ключевое требование: первый и последний элемент массива координат должны совпадать, замыкая контур.
При работе с набором точек проблема заключается в отсутствии естественного порядка обхода границы, что делает невозможным прямое преобразование массива точек в корректный полигон без предварительной обработки.
В Turf.js точка представляется как GeoJSON Feature:
import * as turf from "@turf/turf";
const pt = turf.point([30.5, 50.5]);
Набор точек формируется через FeatureCollection:
const points = turf.featureCollection([
turf.point([30.1, 50.1]),
turf.point([30.2, 50.4]),
turf.point([30.4, 50.2])
]);
FeatureCollection является основой для большинства алгоритмов, связанных с построением геометрий из множества объектов.
Самый простой способ создания полигона — ручное указание упорядоченных координат:
const polygon = turf.polygon([[
[30.0, 50.0],
[30.5, 50.0],
[30.5, 50.5],
[30.0, 50.5],
[30.0, 50.0]
]]);
Этот способ требует заранее известного порядка обхода. В реальных данных точки редко упорядочены корректно, поэтому прямое использование подходит только для синтетических или заранее подготовленных наборов.
Набор точек, полученных из GPS, датчиков или кластеризации, не содержит информации о границе. Прямое соединение в произвольном порядке приводит к самопересечениям:
Поэтому требуется алгоритм построения оболочки.
Одним из базовых способов создания полигона из точек является выпуклая оболочка. Она строит минимальный выпуклый многоугольник, который содержит все точки.
В Turf.js используется функция:
const hull = turf.convex(points);
Алгоритм игнорирует внутреннюю структуру распределения и строит внешнюю границу:
const pts = turf.featureCollection([
turf.point([0, 0]),
turf.point([1, 0.2]),
turf.point([1, 1]),
turf.point([0.2, 1]),
turf.point([0.5, 0.5])
]);
const hull = turf.convex(pts);
Полученный полигон будет обводить крайние точки без учёта внутреннего «выреза».
Для более точного отражения формы используется вогнутая оболочка:
const concave = turf.concave(points, {
maxEdge: 1.5,
units: "kilometers"
});
maxEdge определяет максимальную длину ребра:
В отличие от convex hull:
null, если данных недостаточноConcave hull часто используется для:
Хотя Turf.js напрямую не реализует полноценные alpha shapes как
математический объект, concave является приближением этого
подхода.
Ключевая идея:
Перед применением алгоритмов необходимо нормализовать входные данные.
Удаляются:
const cleaned = turf.featureCollection(
points.features.filter(p => p.geometry?.coordinates)
);
Concave hull требует достаточного количества точек:
Алгоритмы расстояний в Turf.js работают в геодезических координатах,
но параметры (например, maxEdge) зависят от единиц:
Несоответствие единиц приводит к искажению формы.
При наличии нескольких групп точек сначала выполняется разбиение на кластеры.
Типовой подход:
Пример цепочки:
const clusterA = turf.featureCollection([...]);
const clusterB = turf.featureCollection([...]);
const polyA = turf.concave(clusterA, { maxEdge: 2, units: "kilometers" });
const polyB = turf.convex(clusterB);
При построении полигона из точек возникают ограничения:
Concave hull может создавать:
В таких случаях требуется постобработка через:
Порядок обхода влияет на:
Некоторые системы требуют строгое направление внешнего кольца.
После создания полигона часто применяется упрощение:
const simplified = turf.simplify(polygon, {
tolerance: 0.01,
highQuality: true
});
Это уменьшает количество точек без существенной потери формы.
Используется для:
После генерации выполняется валидация:
Пример базовой проверки:
function isValidPolygon(poly) {
const coords = poly.geometry.coordinates[0];
const first = coords[0];
const last = coords[coords.length - 1];
return first[0] === last[0] && first[1] === last[1];
}
В практических задачах используется комбинация методов:
Логика выбора:
Создание полигонов из точек используется в:
Каждый сценарий предъявляет разные требования к точности и гладкости границ, что влияет на выбор алгоритма внутри Turf.js.