Turf.js представляет собой модульную библиотеку для геопространственных вычислений в среде JavaScript, ориентированную на работу с форматом GeoJSON. Основная область применения — выполнение аналитических операций над геометриями непосредственно в браузере или в Node.js без обращения к серверным ГИС-движкам.
Ключевая особенность заключается в том, что Turf.js оперирует чистыми геообъектами и реализует функциональность, характерную для ГИС-систем: вычисление расстояний, площадей, пересечений, буферных зон, проверок принадлежности и множества других операций.
В основе всех вычислений Turf.js лежит спецификация GeoJSON. Любая геометрия представляется в виде стандартных объектов:
Пример точки:
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" });
Поддерживаемые единицы:
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]
});
const grid = turf.pointGrid([37.5, 55.7, 37.8, 55.9], 1, {
units: "kilometers"
});
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"
}
});
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 использует геодезические формулы, учитывающие кривизну Земли. Это отличает его от простых евклидовых вычислений.
Основные последствия:
При обработке больших наборов данных возникают особенности:
Для оптимизации применяются:
[широта, долгота]
вместо [долгота, широта]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 применяется для инкрементального пересчёта геометрий: