GeometryCollection — специальный тип геометрии в
OpenLayers, предназначенный для хранения нескольких геометрических
объектов внутри одной общей структуры. В отличие от классов
MultiPoint, MultiLineString и
MultiPolygon, которые объединяют только однотипные объекты,
GeometryCollection позволяет одновременно хранить точки,
линии, полигоны и любые другие геометрии.
Класс находится в модуле:
import GeometryCollection from 'ol/geom/GeometryCollection.js';
Пример состава коллекции:
Таким образом, одна коллекция может содержать полностью разнородный набор геометрий.
На практике GeometryCollection применяется в ситуациях,
когда несколько объектов логически образуют единое целое.
Типичные сценарии:
Например, условный объект аэропорта может состоять из:
Все эти элементы могут быть объединены в одну
GeometryCollection.
Конструктор принимает массив геометрий.
import GeometryCollection from 'ol/geom/GeometryCollection.js';
import Point from 'ol/geom/Point.js';
import LineString from 'ol/geom/LineString.js';
import Polygon from 'ol/geom/Polygon.js';
const collection = new GeometryCollection([
new Point([30, 50]),
new LineString([
[20, 40],
[40, 60]
]),
new Polygon([
[
[10, 10],
[30, 10],
[30, 30],
[10, 30],
[10, 10]
]
])
]);
В результате создаётся единый объект, содержащий три различные геометрии.
Чаще всего коллекция помещается в объект Feature.
import Feature from 'ol/Feature.js';
const feature = new Feature({
geometry: collection
});
Теперь Feature представляет сразу несколько геометрических сущностей.
Метод getGeometries() возвращает массив всех элементов
коллекции.
const geometries = collection.getGeometries();
console.log(geometries);
Результат:
[
Point,
LineString,
Polygon
]
Полученные объекты являются полноценными экземплярами соответствующих классов.
const geometries = collection.getGeometries();
geometries.forEach((geometry) => {
console.log(geometry.getType());
});
Вывод:
Point
LineString
Polygon
Метод getType() позволяет определить конкретный тип
каждого элемента.
const count = collection.getGeometries().length;
console.log(count);
Результат:
3
Метод setGeometries() полностью заменяет список
объектов.
import Point from 'ol/geom/Point.js';
collection.setGeometries([
new Point([0, 0]),
new Point([10, 10]),
new Point([20, 20])
]);
После выполнения старая коллекция удаляется и создаётся новая структура данных.
Прямого метода addGeometry() в классе нет.
Для добавления необходимо:
Пример:
const geometries = collection.getGeometries();
geometries.push(
new Point([100, 100])
);
collection.setGeometries(geometries);
Аналогичным образом выполняется удаление.
const geometries = collection.getGeometries();
geometries.splice(1, 1);
collection.setGeometries(geometries);
Удаляется элемент с индексом 1.
Любая геометрия OpenLayers поддерживает метод
getType().
console.log(collection.getType());
Результат:
GeometryCollection
Это особенно полезно при обработке различных типов геометрий через общий интерфейс.
Метод getExtent() возвращает общий прямоугольник охвата
всех вложенных геометрий.
const extent = collection.getExtent();
console.log(extent);
Формат результата:
[
minX,
minY,
maxX,
maxY
]
OpenLayers автоматически анализирует все вложенные объекты и вычисляет общий экстент.
const intersects = collection.intersectsExtent([
0,
0,
100,
100
]);
console.log(intersects);
Результат:
true
Если хотя бы одна геометрия пересекает область, метод возвращает
true.
Метод clone() создаёт независимую копию объекта.
const copy = collection.clone();
После клонирования изменения одной коллекции не затрагивают другую.
copy.translate(100, 100);
Исходная коллекция останется без изменений.
Метод translate() сдвигает все вложенные геометрии
одновременно.
collection.translate(50, 20);
Здесь:
Все объекты коллекции перемещаются синхронно.
Метод scale() изменяет размеры всех геометрий.
collection.scale(2);
Координаты будут увеличены в два раза относительно центра масштабирования.
Указание собственного центра:
collection.scale(
2,
2,
[0, 0]
);
Метод rotate() выполняет вращение всей коллекции.
collection.rotate(
Math.PI / 4,
[0, 0]
);
Параметры:
В данном случае выполняется поворот на 45 градусов.
Метод simplify() доступен и для коллекции.
const simplified =
collection.simplify(10);
OpenLayers применяет упрощение ко всем вложенным геометриям, если это поддерживается их типом.
Все геометрии OpenLayers наследуются от класса
Observable.
Поэтому можно отслеживать изменения коллекции.
collection.on('change', () => {
console.log('Geometry changed');
});
При любом изменении геометрии событие будет вызвано автоматически.
Событие возникает не только при изменении самой коллекции, но и при изменении её элементов.
const point = new Point([10, 20]);
const collection =
new GeometryCollection([point]);
collection.on('change', () => {
console.log('Collection updated');
});
point.setCoordinates([50, 50]);
Результат:
Collection updated
Коллекция отслеживает изменения своих дочерних геометрий.
Стандарт GeoJSON содержит собственный тип:
{
"type": "GeometryCollection",
"geometries": []
}
OpenLayers умеет автоматически преобразовывать такие данные в объект
GeometryCollection.
Пример GeoJSON:
{
"type": "GeometryCollection",
"geometries": [
{
"type": "Point",
"coordinates": [30, 50]
},
{
"type": "LineString",
"coordinates": [
[20, 20],
[40, 40]
]
}
]
}
Чтение:
import GeoJSON from 'ol/format/GeoJSON.js';
const format = new GeoJSON();
const geometry =
format.readGeometry(geojsonData);
Тип результата:
geometry instanceof GeometryCollection
const format = new GeoJSON();
const json =
format.writeGeometryObject(
collection
);
Полученный объект:
{
"type": "GeometryCollection",
"geometries": [...]
}
Хранит только точки.
new MultiPoint([
[10, 20],
[30, 40]
]);
Хранит любые типы геометрий.
new GeometryCollection([
new Point([10, 20]),
new LineString([
[0, 0],
[100, 100]
])
]);
MultiLineString содержит исключительно линии.
new MultiLineString([
[
[0, 0],
[10, 10]
],
[
[20, 20],
[30, 30]
]
]);
В GeometryCollection могут одновременно
присутствовать:
[
Point,
LineString,
Polygon
]
MultiPolygon предназначен для набора полигонов.
new MultiPolygon([
polygon1,
polygon2
]);
Если требуется смешение различных типов геометрий, используется
только GeometryCollection.
При работе с большими объёмами данных следует учитывать несколько особенностей.
Каждый элемент коллекции остаётся полноценным объектом OpenLayers.
Например:
new GeometryCollection([
point1,
point2,
point3,
...
]);
Каждая геометрия имеет:
Из-за этого коллекция обычно потребляет больше памяти, чем
специализированные классы MultiPoint,
MultiLineString или MultiPolygon.
Операции:
getExtent()
translate()
rotate()
scale()
simplify()
последовательно выполняются для каждой вложенной геометрии.
Сложность большинства таких операций приблизительно пропорциональна количеству элементов коллекции.
Объект наблюдательного поста:
import GeometryCollection from 'ol/geom/GeometryCollection.js';
import Point from 'ol/geom/Point.js';
import LineString from 'ol/geom/LineString.js';
import Polygon from 'ol/geom/Polygon.js';
const tower = new Point([100, 100]);
const road = new LineString([
[50, 50],
[150, 150]
]);
const territory = new Polygon([
[
[20, 20],
[180, 20],
[180, 180],
[20, 180],
[20, 20]
]
]);
const observationPost =
new GeometryCollection([
tower,
road,
territory
]);
Структура позволяет рассматривать весь объект как единую
геометрическую сущность, сохраняя возможность работы с каждой
составляющей отдельно. Благодаря поддержке трансформаций, сериализации в
GeoJSON, отслеживания изменений и совместимости со всеми механизмами
OpenLayers, GeometryCollection служит универсальным
контейнером для сложных составных геометрий, содержащих объекты
различных типов.