Библиотека Turf.js

Turf.js представляет собой модульную библиотеку для геопространственных вычислений в среде JavaScript, ориентированную на работу с форматом GeoJSON. Основная область применения — выполнение аналитических операций над геометриями непосредственно в браузере или в Node.js без обращения к серверным ГИС-движкам.

Ключевая особенность заключается в том, что Turf.js оперирует чистыми геообъектами и реализует функциональность, характерную для ГИС-систем: вычисление расстояний, площадей, пересечений, буферных зон, проверок принадлежности и множества других операций.


GeoJSON как фундаментальная модель данных

В основе всех вычислений Turf.js лежит спецификация GeoJSON. Любая геометрия представляется в виде стандартных объектов:

  • Point
  • LineString
  • Polygon
  • Feature
  • FeatureCollection

Пример точки:

const point = {
  type: "Feature",
  geometry: {
    type: "Point",
    coordinates: [37.6173, 55.7558]
  },
  properties: {}
};

Пример линии:

const line = {
  type: "Feature",
  geometry: {
    type: "LineString",
    coordinates: [
      [37.6, 55.75],
      [37.7, 55.76]
    ]
  },
  properties: {}
};

Turf.js строго предполагает использование WGS84 (EPSG:4326), где координаты задаются в формате [долгота, широта].


Подключение и установка библиотеки

Библиотека устанавливается через npm:

npm install @turf/turf

Импорт:

import * as turf from "@turf/turf";

Либо использование отдельных модулей для оптимизации:

import distance from "@turf/distance";
import buffer from "@turf/buffer";

Модульная структура позволяет уменьшить размер бандла при использовании сборщиков.


Базовые геометрические операции

Создание объектов

Turf.js предоставляет функции для генерации GeoJSON-объектов:

const pt = turf.point([37.6173, 55.7558]);

const line = turf.lineString([
  [37.6, 55.75],
  [37.7, 55.76]
]);

const poly = turf.polygon([[
  [37.6, 55.75],
  [37.7, 55.75],
  [37.7, 55.8],
  [37.6, 55.8],
  [37.6, 55.75]
]]);

Расстояние между точками

Функция distance вычисляет геодезическое расстояние по поверхности Земли:

const from = turf.point([37.6173, 55.7558]);
const to = turf.point([30.3141, 59.9386]);

const dist = turf.distance(from, to, { units: "kilometers" });

Поддерживаемые единицы:

  • kilometers
  • miles
  • meters
  • radians

Площадь полигона

const poly = turf.polygon([[
  [37.6, 55.75],
  [37.7, 55.75],
  [37.7, 55.8],
  [37.6, 55.8],
  [37.6, 55.75]
]]);

const area = turf.area(poly);

Результат возвращается в квадратных метрах.


Буферные зоны

Операция buffer создаёт геометрию, расширенную на заданное расстояние.

const pt = turf.point([37.6173, 55.7558]);

const buffered = turf.buffer(pt, 5, { units: "kilometers" });

Буфер широко применяется для анализа зон доступности, влияния и поиска пересечений.


Проверка принадлежности точки полигону

const pt = turf.point([37.62, 55.76]);
const poly = turf.polygon([[
  [37.6, 55.75],
  [37.7, 55.75],
  [37.7, 55.8],
  [37.6, 55.8],
  [37.6, 55.75]
]]);

const isInside = turf.booleanPointInPolygon(pt, poly);

Функция возвращает булево значение, определяющее, находится ли точка внутри полигона.


Пересечения и булевы операции

Turf.js поддерживает операции над геометриями:

Пересечение

const poly1 = turf.polygon([[
  [0, 0], [4, 0], [4, 4], [0, 4], [0, 0]
]]);

const poly2 = turf.polygon([[
  [2, 2], [6, 2], [6, 6], [2, 6], [2, 2]
]]);

const intersection = turf.intersect(poly1, poly2);

Результатом становится новый полигон, представляющий общую область.


Объединение

const union = turf.union(poly1, poly2);

Разность

const difference = turf.difference(poly1, poly2);

Работа с линиями

Длина линии

const line = turf.lineString([
  [37.6, 55.75],
  [37.7, 55.76]
]);

const length = turf.length(line, { units: "kilometers" });

Интерполяция точки вдоль линии

const pointAlong = turf.along(line, 10, { units: "kilometers" });

Определение направления

const bearing = turf.bearing(
  turf.point([37.6, 55.75]),
  turf.point([37.7, 55.76])
);

Генерация геометрий и выборок

Случайные точки

const points = turf.randomPoint(50, {
  bbox: [37.5, 55.7, 37.8, 55.9]
});

Сетка (grid)

const grid = turf.pointGrid([37.5, 55.7, 37.8, 55.9], 1, {
  units: "kilometers"
});

Интеграция с Mapbox GL JS

Turf.js часто используется совместно с Mapbox GL JS для динамического анализа данных на карте.

Добавление источника данных

map.addSource("points", {
  type: "geojson",
  data: points
});

Отображение слоя

map.addLayer({
  id: "points-layer",
  type: "circle",
  source: "points",
  paint: {
    "circle-radius": 5,
    "circle-color": "#ff0000"
  }
});

Использование Turf.js для фильтрации данных на карте

Фильтрация точек внутри радиуса

const center = turf.point([37.6173, 55.7558]);
const radius = turf.buffer(center, 2, { units: "kilometers" });

const filtered = turf.pointsWithinPolygon(points, radius);

Результат может быть передан обратно в Mapbox как новый источник:

map.getSource("points").setData(filtered);

Построение интерактивных зон анализа

Комбинация Mapbox GL JS и Turf.js позволяет формировать динамические зоны:

  • радиусы доступности
  • зоны обслуживания
  • тепловые области плотности
  • кластерные области

Пример динамического буфера по клику:

map.on("click", (e) => {
  const center = turf.point([e.lngLat.lng, e.lngLat.lat]);

  const buffer = turf.buffer(center, 3, { units: "kilometers" });

  map.getSource("analysis-zone").setData(buffer);
});

Особенности математических вычислений

Turf.js использует геодезические формулы, учитывающие кривизну Земли. Это отличает его от простых евклидовых вычислений.

Основные последствия:

  • расстояния не линейны в координатах
  • площади корректируются по сфере
  • углы рассчитываются через сферическую геометрию

Производительность и ограничения

При обработке больших наборов данных возникают особенности:

  • вычисления выполняются в JavaScript (CPU-bound)
  • сложные булевы операции затратны
  • большие FeatureCollection могут блокировать основной поток

Для оптимизации применяются:

  • предварительная фильтрация bbox
  • разбиение данных на кластеры
  • использование Web Workers
  • выборочное применение операций

Типовые ошибки при работе с Turf.js

  • использование координат в порядке [широта, долгота] вместо [долгота, широта]
  • применение невалидного GeoJSON
  • смешивание проекций (не WGS84)
  • чрезмерное использование булевых операций на больших полигонах

Комбинирование операций

Turf.js поддерживает композицию функций, позволяя формировать цепочки вычислений:

const center = turf.point([37.6173, 55.7558]);

const bufferZone = turf.buffer(center, 5, { units: "kilometers" });

const pointsInZone = turf.pointsWithinPolygon(points, bufferZone);

const enriched = pointsInZone.features.map(p => {
  const dist = turf.distance(center, p);
  p.properties.distance = dist;
  return p;
});

Аналитические сценарии использования

  • расчет зон покрытия сервисов
  • геокодинг и обратная фильтрация объектов
  • построение маршрутов с промежуточными точками
  • анализ плотности распределения объектов
  • геофенсинг событий в реальном времени

Взаимодействие с потоковыми данными

При работе с обновляющимися данными Turf.js применяется для инкрементального пересчёта геометрий:

  • обновление позиции объектов
  • пересчёт принадлежности зон
  • динамическая агрегация точек
  • перерасчёт расстояний при изменении центра анализа