Трансформация геометрии — это процесс изменения координат объектов на карте с целью изменения их положения, размеров, ориентации или системы координат. В библиотеке OpenLayers трансформации применяются как к отдельным геометрическим объектам, так и к наборам объектов, представленным слоями и источниками данных.
К основным операциям трансформации относятся:
Трансформация позволяет изменять пространственные данные без необходимости создания новых геометрий с нуля.
Все пространственные объекты наследуются от базового класса
Geometry.
Наиболее распространённые типы геометрии:
import Point from 'ol/geom/Point';
import LineString from 'ol/geom/LineString';
import Polygon from 'ol/geom/Polygon';
Примеры создания объектов:
const point = new Point([30, 50]);
const line = new LineString([
[10, 10],
[20, 20],
[30, 15]
]);
const polygon = new Polygon([
[
[0, 0],
[100, 0],
[100, 100],
[0, 100],
[0, 0]
]
]);
Каждый объект содержит набор координат, которые могут быть изменены при помощи трансформаций.
Перед выполнением трансформации полезно понимать, как работают координаты.
Получение координат точки:
const coordinates = point.getCoordinates();
console.log(coordinates);
Изменение координат:
point.setCoordinates([100, 200]);
Для сложных геометрий:
const coords = polygon.getCoordinates();
polygon.setCoordinates(coords);
Практически все трансформации внутри OpenLayers сводятся к изменению координатных массивов.
Для смещения объекта используется метод translate().
Синтаксис:
geometry.translate(deltaX, deltaY);
Где:
deltaX — смещение по оси X;deltaY — смещение по оси Y.Пример:
const point = new Point([100, 100]);
point.translate(50, 25);
console.log(point.getCoordinates());
Результат:
[150, 125]
Геометрия перемещается без изменения размеров и формы.
const line = new LineString([
[0, 0],
[10, 10],
[20, 20]
]);
line.translate(100, 50);
После выполнения:
[
[100, 50],
[110, 60],
[120, 70]
]
Каждая вершина получает одинаковое смещение.
polygon.translate(500, 300);
Все вершины полигона будут перемещены на одинаковое расстояние.
Позволяет изменять размеры объекта.
Синтаксис:
geometry.scale(scaleX, scaleY);
Пример:
polygon.scale(2, 2);
Полигон станет в два раза больше относительно центра.
polygon.scale(2, 1);
Результат:
Такой приём часто используется для создания эффекта растяжения объекта.
По умолчанию масштабирование выполняется относительно центра геометрии.
Можно указать собственную точку привязки:
polygon.scale(
1.5,
1.5,
[0, 0]
);
Третий аргумент задаёт координаты центра трансформации.
Исходный объект:
const rectangle = new Polygon([
[
[0, 0],
[100, 0],
[100, 50],
[0, 50],
[0, 0]
]
]);
Увеличение:
rectangle.scale(3, 3);
Размеры увеличатся в три раза относительно центра объекта.
Синтаксис:
geometry.rotate(angle, anchor);
Параметры:
angle — угол в радианах;anchor — центр вращения.const point = new Point([100, 0]);
point.rotate(
Math.PI / 2,
[0, 0]
);
Поворот на 90 градусов вокруг начала координат.
line.rotate(
Math.PI / 4,
[0, 0]
);
Угол:
Math.PI / 4
соответствует 45 градусам.
| Градусы | Радианы |
|---|---|
| 45° | π / 4 |
| 90° | π / 2 |
| 180° | π |
| 270° | 3π / 2 |
| 360° | 2π |
Поскольку OpenLayers использует радианы, преобразование градусов часто выполняется так:
const radians = degrees * Math.PI / 180;
Получение центра:
import {getCenter} from 'ol/extent';
const center = getCenter(
polygon.getExtent()
);
Вращение:
polygon.rotate(
Math.PI / 6,
center
);
Полигон повернётся на 30 градусов вокруг своего центра.
Трансформации можно выполнять последовательно.
polygon.translate(100, 100);
polygon.scale(2, 2);
polygon.rotate(
Math.PI / 3,
[100, 100]
);
Порядок операций имеет большое значение.
Например:
translate → rotate
и
rotate → translate
могут давать совершенно разные результаты.
Иногда встроенных методов недостаточно.
В этом случае координаты изменяются вручную.
Пример:
const coords = point.getCoordinates();
coords[0] += 50;
coords[1] += 30;
point.setCoordinates(coords);
const coords = line.getCoordinates();
const transformed = coords.map(coord => [
coord[0] + 100,
coord[1] + 50
]);
line.setCoordinates(transformed);
Такой подход позволяет реализовывать любые математические преобразования.
Для сложных преобразований используется метод
applyTransform().
Синтаксис:
geometry.applyTransform(callback);
Функция получает массив координат и изменяет их.
point.applyTransform(function(flatCoords) {
for (let i = 0; i < flatCoords.length; i += 2) {
flatCoords[i] += 100;
flatCoords[i + 1] += 50;
}
});
Получается эквивалент операции перемещения.
line.applyTransform(function(flatCoords) {
for (let i = 0; i < flatCoords.length; i += 2) {
flatCoords[i + 1] =
flatCoords[i + 1] +
Math.sin(flatCoords[i]) * 20;
}
});
Результатом станет волнообразное искажение линии.
Одной из наиболее важных задач является преобразование координат между различными системами координат.
OpenLayers содержит встроенные средства работы с проекциями.
import {transform} from 'ol/proj';
Из географической системы WGS84:
EPSG:4326
в веб-проекцию:
EPSG:3857
const result = transform(
[37.6176, 55.7558],
'EPSG:4326',
'EPSG:3857'
);
const coordinates = transform(
projected,
'EPSG:3857',
'EPSG:4326'
);
Это позволяет отображать данные из GPS, геосервисов и баз данных в нужной системе координат.
Метод transform() имеется и у самой геометрии.
Пример:
point.transform(
'EPSG:4326',
'EPSG:3857'
);
После выполнения координаты объекта будут храниться уже в новой проекции.
polygon.transform(
'EPSG:4326',
'EPSG:3857'
);
Все вершины будут автоматически пересчитаны.
Трансформации изменяют исходный объект.
Для сохранения оригинала используется клонирование.
const copy = polygon.clone();
copy.scale(2, 2);
Исходный полигон останется без изменений.
const original = feature.getGeometry();
const transformed =
original.clone();
transformed.rotate(
Math.PI / 4,
[0, 0]
);
Получаются две независимые версии одной геометрии.
Геометрия обычно находится внутри объекта Feature.
const geometry =
feature.getGeometry();
После этого можно применять любые преобразования:
geometry.translate(
200,
100
);
или
geometry.rotate(
Math.PI / 2,
[0, 0]
);
Карта автоматически отобразит изменения.
Для взаимодействия пользователя с объектами используются специальные взаимодействия OpenLayers.
Наиболее часто применяются:
Подключение взаимодействия:
import Translate from 'ol/interaction/Translate';
import Sel ect from 'ol/interaction/Select';
Создание выбора:
const select =
new Select();
Создание перемещения:
const translate =
new Translate({
features:
select.getFeatures()
});
Добавление на карту:
map.addInteraction(select);
map.addInteraction(
translate
);
Теперь выбранный объект можно перетаскивать мышью.
Взаимодействие Translate генерирует события.
Начало перемещения:
translate.on(
'translatestart',
event => {
console.log(
'Начало'
);
}
);
Процесс перемещения:
translate.on(
'translating',
event => {
console.log(
'Перемещение'
);
}
);
Завершение:
translate.on(
'translateend',
event => {
console.log(
'Завершено'
);
}
);
Это позволяет обновлять интерфейс, сохранять изменения и выполнять дополнительную обработку данных.
При работе с большим количеством объектов рекомендуется:
applyTransform() для массовой обработки
координат;Для тысяч объектов эффективность математических операций над координатами напрямую влияет на производительность приложения.
Создание полигона:
const polygon = new Polygon([
[
[0, 0],
[50, 0],
[50, 50],
[0, 50],
[0, 0]
]
]);
Получение центра:
import {getCenter} fr om 'ol/extent';
const center =
getCenter(
polygon.getExtent()
);
Последовательность преобразований:
polygon.translate(
100,
100
);
polygon.scale(
1.5,
1.5
);
polygon.rotate(
Math.PI / 4,
center
);
В результате объект:
Подобная комбинация операций широко применяется в геоинформационных системах, редакторах карт, инструментах проектирования территорий и приложениях пространственного анализа данных.