В OpenLayers вся работа с векторной графикой строится вокруг
геометрий: точек, линий и полигонов. Базовый класс
ol/geom/Geometry задаёт общий интерфейс для всех
пространственных объектов, а конкретные реализации (Point,
LineString, Polygon,
MultiPolygon) используются для описания реальных данных на
карте.
Каждый объект геометрии содержит координаты в системе координат карты
(обычно EPSG:3857 или EPSG:4326) и может быть связан с объектом
Feature, который, в свою очередь, отображается через слой
VectorLayer.
Важно понимать, что сама библиотека OpenLayers не является полнофункциональной ГИС-системой для булевых операций над полигонами, поэтому операции пересечения и объединения чаще реализуются через внешние геометрические библиотеки, интегрированные в поток обработки данных.
Пересечение — это геометрическая операция, которая возвращает область, общую для двух фигур.
Для полигонов это может быть:
Наиболее популярный способ работы с пересечениями в связке с OpenLayers — библиотека Turf.js.
Turf предоставляет функцию intersect, которая принимает
GeoJSON-геометрии.
import { Feature } from 'ol';
import Polygon from 'ol/geom/Polygon';
import * as turf from '@turf/turf';
// OpenLayers полигоны
const poly1 = new Polygon([[
[0, 0],
[10, 0],
[10, 10],
[0, 10],
[0, 0]
]]);
const poly2 = new Polygon([[
[5, 5],
[15, 5],
[15, 15],
[5, 15],
[5, 5]
]]);
// преобразование в GeoJSON
const turfPoly1 = turf.polygon(poly1.getCoordinates());
const turfPoly2 = turf.polygon(poly2.getCoordinates());
// пересечение
const intersect = turf.intersect(turfPoly1, turfPoly2);
if (intersect) {
const resultGeom = new Polygon(intersect.geometry.coordinates);
}
Библиотека JSTS реализует алгоритмы, основанные на JTS (Java Topology Suite), и поддерживает более точные операции пересечения.
import GeoJSON from 'ol/format/GeoJSON';
import { GeometryFactory } from 'jsts/org/locationtech/jts/geom/GeometryFactory';
import { WKTReader } from 'jsts/org/locationtech/jts/io/WKTReader';
import { GeoJSONReader, GeoJSONWriter } from 'jsts/org/locationtech/jts/io';
const reader = new GeoJSONReader();
const writer = new GeoJSONWriter();
const geom1 = reader.read({
type: "Polygon",
coordinates: [[[0,0],[10,0],[10,10],[0,10],[0,0]]]
});
const geom2 = reader.read({
type: "Polygon",
coordinates: [[[5,5],[15,5],[15,15],[5,15],[5,5]]]
});
const intersection = geom1.intersection(geom2);
const resultGeoJSON = writer.write(intersection);
После получения GeoJSON результат легко конвертируется обратно в геометрию OpenLayers:
import GeoJSON from 'ol/format/GeoJSON';
const format = new GeoJSON();
const feature = format.readFeature(resultGeoJSON, {
featureProjection: 'EPSG:3857'
});
Объединение создаёт одну геометрию, охватывающую все входные объекты.
Результаты:
В Turf.js существует функция union, позволяющая
объединять полигоны.
import * as turf from '@turf/turf';
const poly1 = turf.polygon([[
[0, 0],
[10, 0],
[10, 10],
[0, 10],
[0, 0]
]]);
const poly2 = turf.polygon([[
[5, 5],
[15, 5],
[15, 15],
[5, 15],
[5, 5]
]]);
const union = turf.union(poly1, poly2);
JSTS обеспечивает более стабильное объединение сложных геометрий:
const geomUnion = geom1.union(geom2);
При работе с множеством объектов используется итеративное объединение:
let result = geometries[0];
for (let i = 1; i < geometries.length; i++) {
result = result.union(geometries[i]);
}
Операции пересечения и объединения обычно применяются к
Feature из VectorSource.
import VectorSource from 'ol/source/Vector';
import Feature from 'ol/Feature';
const source = new VectorSource();
const features = source.getFeatures();
let geom = features[0].getGeometry();
for (let i = 1; i < features.length; i++) {
const g = features[i].getGeometry();
// здесь применяется JSTS или Turf (через GeoJSON)
geom = geom.union(g); // псевдокод, зависит от библиотеки
}
Используется для:
Методы:
geometry.intersectsExtent(extent) — проверка
пересечения с bounding box,feature.getGeometry().intersectsCoordinate() — проверка
попадания точки.const extent = [0, 0, 100, 100];
if (geometry.intersectsExtent(extent)) {
// объект частично попадает в область
}
При работе с большими наборами данных важно учитывать производительность.
Перед сложными операциями выполняется быстрый отсев:
if (!geom1.intersectsExtent(geom2.getExtent())) {
return null;
}
Для ускорения вычислений:
import { simplify } from 'ol/geom/Geometry';
const simplified = geometry.simplify(10);
При объединении часто возникает переход к
MultiPolygon:
JSTS автоматически возвращает корректный тип геометрии, в то время как Turf может требовать дополнительной обработки результата.
const coverage = turf.union(zoneA, zoneB);
const overlap = turf.intersect(coverage, requestZone);
После вычислений результат добавляется в слой OpenLayers:
const feature = new Feature({
geometry: new Polygon(resultCoords)
});
vectorSource.addFeature(feature);
Стилизация позволяет выделить:
import Style from 'ol/style/Style';
import Fill from 'ol/style/Fill';
const style = new Style({
fill: new Fill({
color: 'rgba(255, 0, 0, 0.3)'
})
});
Критически важно, чтобы все операции выполнялись в одной системе координат:
Перед вычислениями выполняется трансформация:
geometry.transform('EPSG:3857', 'EPSG:4326');
Типичные проблемы:
JSTS обычно корректнее обрабатывает топологические ошибки, чем Turf.
В реальных приложениях часто используется гибрид:
Такой стек позволяет разделить ответственность между слоями системы и обеспечить баланс между скоростью и точностью.