Объединение полигонов — одна из наиболее распространённых геопространственных операций в Turf.js. Она позволяет преобразовать несколько пересекающихся или соприкасающихся полигонов в единый объект. Такая операция используется при анализе территорий, работе с административными границами, обработке зон покрытия, объединении земельных участков и подготовке данных для последующих вычислений.
В Turf.js для выполнения этой задачи применяется функция
union.
Основная идея заключается в том, что несколько отдельных областей превращаются в один геометрический объект, который охватывает всю их суммарную площадь без дублирования пересекающихся частей.
Рассмотрим два полигона:
Если полигоны пересекаются, после объединения получится единая территория, включающая обе области.
До объединения:
+---------+
| |
| +---------+
| | | |
+----|----+ |
| |
+---------+
После объединения:
+--------------+
| |
| |
| |
| |
+--------------+
Пересекающаяся часть становится частью общей геометрии и не учитывается дважды.
Установка через npm:
npm install @turf/turf
Импорт всей библиотеки:
import * as turf from "@turf/turf";
Импорт только необходимой функции:
import { union } from "@turf/turf";
Для объединения понадобятся как минимум два полигона.
import * as turf from "@turf/turf";
const polygon1 = turf.polygon([
[
[0, 0],
[4, 0],
[4, 4],
[0, 4],
[0, 0]
]
]);
const polygon2 = turf.polygon([
[
[2, 2],
[6, 2],
[6, 6],
[2, 6],
[2, 2]
]
]);
Полученные объекты являются GeoJSON-полигонами:
console.log(polygon1);
console.log(polygon2);
Современные версии Turf.js используют объект
FeatureCollection.
const collection = turf.featureCollection([
polygon1,
polygon2
]);
const result = turf.union(collection);
Результат:
console.log(result);
Вывод будет содержать новый полигон, охватывающий обе области.
Исходные полигоны:
const polygon1 = turf.polygon([
[
[0, 0],
[4, 0],
[4, 4],
[0, 4],
[0, 0]
]
]);
const polygon2 = turf.polygon([
[
[2, 2],
[6, 2],
[6, 6],
[2, 6],
[2, 2]
]
]);
После объединения координаты могут выглядеть следующим образом:
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [...]
}
}
Точный набор координат зависит от формы исходных объектов.
Необязательно, чтобы полигоны пересекались.
const polygon1 = turf.polygon([
[
[0, 0],
[2, 0],
[2, 2],
[0, 2],
[0, 0]
]
]);
const polygon2 = turf.polygon([
[
[5, 0],
[7, 0],
[7, 2],
[5, 2],
[5, 0]
]
]);
Объединение:
const result = turf.union(
turf.featureCollection([
polygon1,
polygon2
])
);
В этом случае результатом обычно становится объект типа
MultiPolygon.
console.log(result.geometry.type);
Результат:
MultiPolygon
Это связано с тем, что между областями отсутствует общая граница.
После объединения результат может иметь разные типы геометрии.
Возвращается, если области образуют единую непрерывную фигуру.
{
"type": "Polygon"
}
Возвращается, если области остаются раздельными.
{
"type": "MultiPolygon"
}
Поэтому после вызова union рекомендуется проверять тип
результата.
if (result.geometry.type === "Polygon") {
console.log("Один полигон");
}
if (result.geometry.type === "MultiPolygon") {
console.log("Несколько независимых полигонов");
}
На практике часто требуется объединить десятки или сотни объектов.
const collection = turf.featureCollection([
polygon1,
polygon2,
polygon3,
polygon4,
polygon5
]);
const merged = turf.union(collection);
Такой подход значительно удобнее последовательного объединения каждого объекта вручную.
Каждый полигон может содержать атрибуты.
const polygon1 = turf.polygon(
[[
[0,0],
[4,0],
[4,4],
[0,4],
[0,0]
]],
{
name: "Zone A"
}
);
const polygon2 = turf.polygon(
[[
[2,2],
[6,2],
[6,6],
[2,6],
[2,2]
]],
{
name: "Zone B"
}
);
После объединения свойства автоматически не комбинируются логически.
const merged = turf.union(
turf.featureCollection([
polygon1,
polygon2
])
);
При необходимости итоговые свойства задаются вручную:
merged.properties = {
name: "Combined Zone"
};
Часто требуется убедиться, что объединение прошло корректно.
Для этого можно использовать функцию area.
const area1 = turf.area(polygon1);
const area2 = turf.area(polygon2);
Площадь объединённой фигуры:
const merged = turf.union(
turf.featureCollection([
polygon1,
polygon2
])
);
const mergedArea = turf.area(merged);
Сравнение:
console.log(area1);
console.log(area2);
console.log(mergedArea);
Если полигоны пересекаются, то:
mergedArea < area1 + area2
Пересекающаяся область учитывается только один раз.
Один из наиболее частых сценариев — объединение нескольких районов в единый регион.
Исходные данные:
const districts = turf.featureCollection([
districtA,
districtB,
districtC
]);
Объединение:
const region = turf.union(districts);
Полученный объект можно использовать для:
Предположим, имеются несколько зон действия базовых станций.
const coverage = turf.featureCollection([
tower1,
tower2,
tower3
]);
Объединение:
const totalCoverage = turf.union(coverage);
После этого становится возможным вычисление общей зоны обслуживания.
const totalArea = turf.area(totalCoverage);
Буферизация и объединение часто используются совместно.
Создание буферов:
const buffer1 = turf.buffer(point1, 5);
const buffer2 = turf.buffer(point2, 5);
const buffer3 = turf.buffer(point3, 5);
Объединение буферов:
const mergedBuffer = turf.union(
turf.featureCollection([
buffer1,
buffer2,
buffer3
])
);
Такой подход позволяет получить единую зону влияния нескольких объектов.
После выполнения операции рекомендуется проверить результат.
const merged = turf.union(collection);
Проверка:
if (!merged) {
console.log("Объединение невозможно");
}
Далее можно обращаться к геометрии:
console.log(merged.geometry);
Или к координатам:
console.log(
merged.geometry.coordinates
);
При работе с тысячами полигонов операция объединения может занимать заметное время.
Основные причины:
Для повышения производительности применяются следующие подходы:
const simplified = turf.simplify(
polygon,
{
tolerance: 0.001,
highQuality: false
}
);
Группировка объектов по регионам.
Выполнение обработки пакетами.
Исключение заведомо удалённых объектов.
Неверно:
[
[0,0],
[5,0],
[5,5],
[0,5]
]
Верно:
[
[0,0],
[5,0],
[5,5],
[0,5],
[0,0]
]
Первая и последняя координаты должны совпадать.
Формат GeoJSON использует порядок:
[longitude, latitude]
Правильно:
[37.6176, 55.7558]
Неправильно:
[55.7558, 37.6176]
Самопересекающиеся полигоны способны привести к ошибкам геометрических операций.
Пример проблемного контура:
[
[0,0],
[5,5],
[0,5],
[5,0],
[0,0]
]
Подобные фигуры рекомендуется исправлять до выполнения объединения.
Объединяет области.
const result = turf.union(collection);
Результат содержит всю площадь всех объектов.
Находит только общую часть.
const result = turf.intersect(collection);
Возвращается пересечение фигур.
Вычитает один полигон из другого.
const result = turf.difference(collection);
Остаётся часть первой фигуры без второй.
Используется для объединения множества объектов по общему признаку и часто применяется при агрегации геоданных.
Пусть имеются три пересекающиеся территории.
const zones = turf.featureCollection([
turf.polygon([
[
[0,0],
[4,0],
[4,4],
[0,4],
[0,0]
]
]),
turf.polygon([
[
[2,2],
[6,2],
[6,6],
[2,6],
[2,2]
]
]),
turf.polygon([
[
[5,1],
[8,1],
[8,4],
[5,4],
[5,1]
]
])
]);
Выполнение объединения:
const merged = turf.union(zones);
Расчёт площади:
const area = turf.area(merged);
console.log(area);
Проверка типа результата:
console.log(
merged.geometry.type
);
Полученный объект представляет единую геометрию, пригодную для дальнейшего пространственного анализа, визуализации на картах и выполнения других операций Turf.js.