Операция поворота в пространственной геометрии сводится к преобразованию координат каждого узла объекта относительно выбранной опорной точки (pivot). В контексте GeoJSON это означает, что каждая вершина Point, LineString или Polygon проходит через аффинное преобразование, основанное на матрице поворота в двумерной плоскости.
В геоинформационных вычислениях поворот используется для нормализации данных, моделирования ориентации объектов, генерации симметрий, анализа пространственных конфигураций и подготовки геометрий к последующим операциям (например, упаковке в bounding box или проверке пересечений в упрощённых координатных системах).
Пусть имеется точка в декартовой системе координат:
x, y
Поворот на угол θ вокруг начала координат описывается преобразованием:
x’ = x · cos(θ) − y · sin(θ) y’ = x · sin(θ) + y · cos(θ)
Если поворот выполняется вокруг произвольной точки pivot (px, py), применяется последовательность:
Сдвиг системы координат в начало: x = x − px y = y − py
Применение матрицы поворота
Возврат в исходную систему: x’ = x’ + px y’ = y’ + py
Эта схема используется во всех геометрических операциях поворота в Turf.js.
В Turf.js поворот реализуется через модуль transform-rotate:
turf.transformRotate(geojson, angle, options)
Функция принимает GeoJSON-объект и возвращает новый объект с преобразованной геометрией.
Угол поворота в градусах.
Turf.js работает в градусной системе, что важно при интеграции с географическими координатами WGS84.
Точка вращения. Формат:
[pivotX, pivotY]
Если не задан, используется центр bounding box геометрии.
Булевый флаг:
Иногда поддерживаются единицы интерпретации угла или вспомогательные параметры, однако стандартная реализация ориентирована на градусы.
Для одиночной точки преобразование сводится к одной операции над координатами:
import { point } from "@turf/helpers";
import transformRotate from "@turf/transform-rotate";
const pt = point([30, 10]);
const rotated = transformRotate(pt, 45);
Точка вращается вокруг центра bounding box (в данном случае совпадающего с самой точкой), поэтому визуально координаты остаются неизменными. Реальный эффект проявляется при наличии pivot.
LineString представляет собой упорядоченный набор точек, каждая из которых преобразуется независимо.
import { lineString } from "@turf/helpers";
import transformRotate from "@turf/transform-rotate";
const line = lineString([
[0, 0],
[10, 0],
[10, 10]
]);
const rotatedLine = transformRotate(line, 30, {
pivot: [0, 0]
});
При задании pivot в начале координат вся линия вращается как жёсткое тело, сохраняя геометрию сегментов.
Polygon в GeoJSON состоит из внешнего кольца и внутренних колец (дыр). Поворот применяется ко всем координатам всех колец без изменения топологии.
import { polygon } from "@turf/helpers";
import transformRotate from "@turf/transform-rotate";
const poly = polygon([[
[0, 0],
[10, 0],
[10, 10],
[0, 10],
[0, 0]
]]);
const rotatedPoly = transformRotate(poly, -45, {
pivot: [5, 5]
});
Использование центра полигона как pivot сохраняет его положение в пространстве, меняя только ориентацию.
Pivot определяет поведение всего преобразования.
Используется, когда pivot не указан. Алгоритм:
Этот вариант подходит для визуальных трансформаций.
Часто используется для симметричных операций:
Пример:
const rotated = transformRotate(geom, 90, {
pivot: [100, 50]
});
В системах координат WGS84 pivot задаётся в долготе/широте. Это означает, что поворот выполняется в плоской проекции, что приводит к допустимым искажениям на больших масштабах.
Turf.js работает в геодезической системе координат, но математические операции выполняются в евклидовой плоскости.
Следствия:
При необходимости высокой точности используются проекционные преобразования до применения rotate.
Процесс обработки геометрии включает следующие этапы:
Деконструкция GeoJSON в массив координат
Вычисление pivot (если отсутствует)
Итерация по каждой координате:
Сборка новой геометрии
Для каждого узла выполняется независимое преобразование без сохранения промежуточных связей.
import { featureCollection, point, lineString, polygon } from "@turf/helpers";
import transformRotate from "@turf/transform-rotate";
const fc = featureCollection([
point([2, 3]),
lineString([[0, 0], [5, 5]]),
polygon([[[0, 0], [4, 0], [4, 4], [0, 4], [0, 0]]])
]);
const rotated = transformRotate(fc, 120, {
pivot: [2, 2],
mutate: false
});
FeatureCollection поддерживается напрямую: каждая вложенная геометрия обрабатывается рекурсивно.
Использование pivot вне области данных приводит к смещению всей геометрии без ожидаемого центра вращения.
Предположение о плоской метрике в градусной системе приводит к неправильной интерпретации расстояний после вращения.
При mutate: true исходный объект изменяется, что может нарушить цепочки геообработки.
Площадь полигона в градусах не является метрической величиной, поэтому визуальная стабильность не гарантирует геометрическую эквивалентность в реальных единицах измерения.
Операция rotate часто используется как промежуточный шаг:
В связке с другими функциями Turf.js (buffer, centroid, transformScale) поворот формирует основу аффинных преобразований пространственных данных.