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

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

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

Ограничивающий прямоугольник (bbox)​

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

const line = turf.lineString([
[32.013931, 55.491648],
[35.491901, 56.392901],
[37.144102, 55.491648],
[40.371536, 56.392901],
[42.128462, 55.491648],
]);
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([
[32.013931, 55.491648],
[35.491901, 56.392901],
[37.144102, 55.491648],
[40.371536, 56.392901],
[42.128462, 55.491648],
]);
const convexHull = turf.convex(line);

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

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

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

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

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

const line = turf.lineString([
[32.013931, 55.491648],
[35.491901, 56.392901],
[37.144102, 55.491648],
[40.371536, 56.392901],
[42.128462, 55.491648],
]);
const buffer = turf.buffer(line, 40);

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

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

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

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

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

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

const polygon = turf.polygon([
[
[32.013931, 55.491648],
[35.491901, 56.392901],
[37.144102, 55.491648],
[40.371536, 56.392901],
[42.128462, 55.491648],
[32.013931, 55.491648],
],
]);
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([
[32.013931, 55.491648],
[35.491901, 56.392901],
[37.144102, 55.491648],
[40.371536, 56.392901],
[42.128462, 55.491648],
]);
const target = turf.point([35.491901, 55.491648]);

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

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

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

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

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

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

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

const line = turf.lineString([
[32.013931, 55.491648],
[35.491901, 56.392901],
[37.144102, 55.491648],
[40.371536, 56.392901],
[42.128462, 55.491648],
]);
const target = turf.point([35.491901, 55.491648], { name: 'Target' });

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

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

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

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

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

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

const points = [
[38.771739, 55.491648],
[37.144102, 56.392901],
];
const circleA = turf.buffer(turf.point([38.771739, 55.491648]), 150);
const circleB = turf.buffer(turf.point([37.144102, 56.392901]), 150);
const united = turf.union(circleA, circleB);

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

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

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

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

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

const points = [
[32.013931, 55.491648],
[35.491901, 56.392901],
];
const circleA = turf.buffer(turf.point([38.771739, 55.491648]), 150);
const circleB = turf.buffer(turf.point([37.144102, 56.392901]), 150);
const intersected = turf.intersect(circleA, circleB);

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

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

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

Маска (mask)​

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

const poly = turf.polygon([
[
[36.803769, 56.009657],
[37.142487, 56.164165],
[37.841187, 56.120356],
[38.199158, 55.907578],
[38.202972, 55.591507],
[37.834930, 55.311997],
[37.131653, 55.305538],
[36.586609, 55.484630],
[36.365356, 55.818146],
[36.803769, 56.009657],
],
]);
turf.mask(poly);

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

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

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

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

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

const gpsTrack = turf.lineString([
[37.588144, 55.733842],
[37.593771, 55.740372],
[37.601547, 55.742088],
[37.608223, 55.750391],
]);
const simplifiedTrack = turf.simplify(gpsTrack, { tolerance: 0.2 });
// { ... geometry: { ..., coordinates: [[37.588144, 55.733842], [37.601547, 55.742088], [37.608223, 55.750391]] } }

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

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

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

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