Перейти к основному содержимому

Работа с геометриями

Для манипуляций с GeoJSON рекомендуется использовать библиотеку turf.js. Ниже описывается использование данной библиотеки в связке с MapGL JS API.

Граничный прямоугольник (bbox)

Метод turf.bbox рассчитывает прямоугольную область, в которой находятся заданные объекты или группа объектов.

const line = turf.lineString([
[34, 40],
[36, 41],
[41, 37],
[48, 42],
[42, 35],
]);
const bbox = turf.bbox(line); // [minX, minY, maxX, maxY]

Документация на метод: @turf/bbox

Примеры использования

  • Спозиционировать карту так, чтобы все объекты поместились на экран при помощи метода map.fitBounds.

    map.fitBounds({ southWest: bbox.slice(0, 2), northEast: bbox.slice(2, 4) });
  • Запросить дополнительные данные к имеющимся. Например, имея полигоны муниципальных районов, запросить близлежащие объекты застройки.

Граничный прямоугольник является наиболее распространенным и быстрым способом определить границы нахождения объектов. Обратной стороной является то, что границы таким образом определяются достаточно грубо. Если нужна большая точность, воспользуйтесь выпуклой оболочкой.



Выпуклая оболочка (convex hull)

Метод turf.convex принимает на вход объект или группу объектов и создаёт на их основе выпуклую оболочку.

const line = turf.lineString([
[34, 40],
[36, 41],
[41, 37],
[48, 42],
[42, 35],
]);
const convexHull = turf.convex(line);

Документация на метод: @turf/convex

Пример использования

Выпуклая оболочка — более точный по сравнению с граничным прямоугольником метод определения границ объекта. Обратной стороной является большая вычислительная сложность данного метода.



Буфер вокруг объекта (buffer)

Метод turf.buffer позволяет пропорционально увеличить или уменьшить объект.

const line = turf.lineString([
[34, 40],
[36, 41],
[41, 37],
[48, 42],
[42, 35],
]);
const buffer = turf.buffer(line, 40);

Документация на метод: @turf/buffer

Примеры использования

  • Отобразить различного рода охранные зоны, полосы отчуждения и т.п.


  • Показать на карте места, равноудаленные от какого-либо объекта.

    Однако это работает хорошо только на малых расстояниях (до 50-100 м). При расчёте больших расстояний начинает сказываться тот факт, что turf.buffer рассчитывает удалённость чисто геометрически, а в действительности на кратчайшем геометрическом пути обычно содержатся препятствия: дома, реки, заборы, которые требуется обходить/объезжать. В этом случае нужно применять более точный и специализированный инструмент: изохроны.


Получение центра (centroid)

Методы turf.center, turf.centroid и turf.centerOfMass позволяют получить тот или иной центр объекта или группы объектов.

const polygon = turf.polygon([
[
[34, 40],
[36, 41],
[41, 37],
[48, 42],
[42, 35],
[34, 40],
],
]);
const center = turf.center(polygon);
const centroid = turf.centroid(polygon);
const centerOfMass = turf.centerOfMass(polygon);

Документация на методы:

Примеры использования

Есть 3 метода получения центра:

  • center получает центр граничного прямоугольника объекта или группы.
  • centroid вычисляет геометрический центр объекта или группы.
  • centerOfMass получает центр масс фигуры.

На правильных и симметричных полигонах между этими методами практически нет разницы. В случае невыпуклых полигонов или других полигонов неправильной формы лучше всего работает centerOfMass.

Эти методы удобны для расстановки подписей объектов.



Ближайшая точка (nearestPoint)

Метод turf.nearestPoint получает ближайшую точку из множества точек.

const line = turf.lineString([
[34, 40],
[36, 41],
[41, 37],
[48, 42],
[42, 35],
]);
const target = turf.point([38, 38]);

const points = turf.explode(line);
const nearest = turf.nearestPoint(target, points);

Документация на метод: @turf/nearestPoint

Особенностью метода является работа только с множеством точек. Чтобы преобразовать произвольный объект в множество точек, воспользуйтесь методом @turf/explode.

Пример использования

Найти ближайший к заданному объект.


Точка на линии (nearestPointOnLine)

Метод turf.nearestPointOnLine получает ближайшую к заданной точку на линии или на группе линий.

const line = turf.lineString([
[34, 40],
[36, 41],
[41, 37],
[48, 42],
[42, 35],
]);
const target = turf.point([38, 38], { name: 'Target' });

const nearestOnLine = turf.nearestPointOnLine(line, target);

Документация на метод: @turf/nearestPointOnLine

Пример использования

Найти ближайшую точку на маршруте или дороге. Как и в случае с методом turf.buffer, это работает только в самых простых случаях, когда не требуется учитывать препятствия на местности. В остальных случаях воспользуйтесь API маршрутизации.



Объединение (union)

Метод turf.union объединяет несколько фигур в одну.

const points = [
[10, 10],
[12, 10],
];
const circleA = turf.buffer(turf.point([10, 10]), 300);
const circleB = turf.buffer(turf.point([12, 10]), 300);
const united = turf.union(circleA, circleB);

Документация на метод: @turf/union

Примеры использования

  • Отобразить на карте область, которую составляют несколько объектов, как один объект.
  • Собрать излишне фрагментированные объекты, что иногда случается при обработке геоданных.

Пересечение (intersect)

Метод turf.intersect находит фигуру, образованную пересечением заданных фигур.

const points = [
[10, 10],
[12, 10],
];
const circleA = turf.buffer(turf.point([10, 10]), 300);
const circleB = turf.buffer(turf.point([12, 10]), 300);
const intersected = turf.intersect(circleA, circleB);

Документация на метод: @turf/intersect

Пример использования

Отобразить на карте область, являющуюся пересечением других областей. Например, бесплатную парковку в пределах заданного радиуса от объекта.



Маска (mask)

Метод turf.mask позволяет «вывернуть наизнанку» полигон: превратить остальное пространство вокруг него в полигон.

const poly = turf.polygon([
[
[0, 0],
[0, 2],
[2, 2],
[2, 0],
[0, 0],
],
]);
turf.mask(poly);

Документация на метод: @turf/mask

Пример использования

Акцентировать внимание на одной или нескольких областях карты и затенить остальное пространство.



Упрощение (simplify)

Метод turf.simplify упрощает геометрию при помощи алгоритма Рамера-Дугласа-Пекера.

const gpsTrack = turf.lineString([
[0, 0],
[0, 0.1],
[0.5, 0.5],
[1, 0.5],
]);
const simplifiedTrack = turf.simplify(gpsTrack, { tolerance: 0.2 });
// { ... geometry: { ..., coordinates: [[0, 0], [0.5, 0.5], [1, 0.5]] } }

Степень упрощения геометрии определяется параметром tolerance, который обозначает максимальную ошибку, которую может допустить алгоритм при упрощении. Величина tolerance имеет ту же размерность, что и исходные данные. То есть, если геокоординаты указываются в градусах, то и tolerance будет в градусах.

Документация на метод: @turf/simplify

Примеры использования

  • Получить менее сложные геометрии, которые будут отрисовываться быстрее.
  • Отфильтровать данные, когда известно, что их точность не может превышать определённое значение.
  • Отобразить точные данные на большом масштабе: упрощённые геометрии имеют более эстетичный внешний вид и плавные линии без визуального шума.