В Turf.js вычисления строятся вокруг неизменяемых геообъектов GeoJSON, а каждая операция рассматривается как чистая функция: на вход подаётся Feature, FeatureCollection или Geometry, на выходе получается новый объект. Такая модель естественным образом формирует композицию операций, где результат одного шага становится входом следующего.
Ключевая особенность — отсутствие скрытого состояния. Любое преобразование не модифицирует исходные данные, что позволяет выстраивать предсказуемые цепочки геоаналитики.
import * as turf from "@turf/turf";
const point = turf.point([30.5, 50.5]);
const buffered = turf.buffer(point, 5, { units: "kilometers" });
const result = turf.area(buffered);
В этом примере уже присутствует базовая форма композиции: геометрия → буферизация → вычисление метрики.
Композиция операций в Turf.js опирается на функциональный стиль программирования. Каждая функция:
Это создаёт основу для построения конвейеров обработки:
const pipeline = (point) => {
const buffered = turf.buffer(point, 10, { units: "kilometers" });
const simplified = turf.simplify(buffered, { tolerance: 0.01 });
return turf.bbox(simplified);
};
Здесь каждая стадия формирует промежуточный результат, пригодный для следующего шага.
Наиболее распространённый сценарий — последовательное применение пространственных операций.
const a = turf.point([30, 50]);
const b = turf.point([30.1, 50.1]);
const bufferA = turf.buffer(a, 20, { units: "kilometers" });
const bufferB = turf.buffer(b, 20, { units: "kilometers" });
const intersection = turf.intersect(bufferA, bufferB);
Здесь формируется композиция двух типов операций:
Результат зависит от промежуточных объектов, а не от исходных точек напрямую.
При работе с наборами данных композиция приобретает более структурный характер.
const points = turf.featureCollection([
turf.point([30, 50]),
turf.point([30.2, 50.2]),
turf.point([30.4, 50.4])
]);
const buffered = turf.buffer(points, 10, { units: "kilometers" });
const dissolved = turf.dissolve(buffered);
const convex = turf.convex(dissolved);
Здесь формируется цепочка:
Каждый этап абстрагирует предыдущий уровень геометрической детализации.
Композиция часто строится вокруг нормализации данных перед основным анализом.
const normalize = (fc) => {
const cleaned = turf.cleanCoords(fc);
const simplified = turf.simplify(cleaned, { tolerance: 0.005 });
return turf.truncate(simplified, { precision: 6 });
};
Такая функция сама по себе становится компонентом более сложных пайплайнов.
Turf.js позволяет комбинировать предикаты и геометрические операции.
const polygon = turf.polygon([[
[30, 50],
[31, 50],
[31, 51],
[30, 51],
[30, 50]
]]);
const pt = turf.point([30.3, 50.3]);
const inside = turf.booleanPointInPolygon(pt, polygon);
const buffered = turf.buffer(polygon, 5, { units: "kilometers" });
const expandedCheck = turf.booleanPointInPolygon(pt, buffered);
Здесь композиция выражается не только через преобразования, но и через последовательные проверки пространственных отношений.
Композиция часто используется для построения маршрутов или оценок близости.
const start = turf.point([30, 50]);
const end = turf.point([31, 51]);
const distance = turf.distance(start, end, { units: "kilometers" });
const midpoint = turf.midpoint(start, end);
const line = turf.lineString([start.geometry.coordinates, end.geometry.coordinates]);
Расширение этого подхода позволяет формировать цепочки анализа:
FeatureCollection естественно сочетается с функциональными методами массива.
const buffered = turf.featureCollection(
points.features.map((p) =>
turf.buffer(p, 5, { units: "kilometers" })
)
);
const merged = buffered.features.reduce((acc, feature) => {
return acc ? turf.union(acc, feature) : feature;
}, null);
Такой подход превращает Turf.js в геопространственный слой поверх стандартных функциональных конструкций JavaScript.
При построении аналитических моделей операции объединяются в многоступенчатые цепочки.
const analyze = (fc) => {
const buffered = turf.buffer(fc, 2, { units: "kilometers" });
const dissolved = turf.dissolve(buffered);
const simplified = turf.simplify(dissolved, { tolerance: 0.01 });
const bbox = turf.bboxPolygon(turf.bbox(simplified));
return bbox;
};
Каждый этап выполняет отдельную роль:
Корректная композиция операций требует согласованности пространственных систем.
const projected = turf.toMercator(point);
const buffer = turf.buffer(projected, 1000, { units: "meters" });
const geographic = turf.toWgs84(buffer);
Цепочка преобразований координат становится частью общей композиционной структуры, особенно при смешивании локальных и глобальных расчётов.
Композиция часто оформляется как переиспользуемые функции.
const buildInfluenceZone = (feature, radius) => {
const buffer = turf.buffer(feature, radius, { units: "kilometers" });
const simplified = turf.simplify(buffer, { tolerance: 0.02 });
return turf.cleanCoords(simplified);
};
Такие конструкции позволяют формировать библиотеку доменных геоопераций поверх Turf.js.
При построении цепочек важным аспектом становится стабильность промежуточных результатов:
Поэтому композиция часто включает балансирующие операции:
const stablePipeline = (fc) => {
const clipped = turf.bboxClip(fc, turf.bbox(fc));
const simplified = turf.simplify(clipped, { tolerance: 0.005 });
return turf.truncate(simplified, { precision: 5 });
};
При анализе нескольких слоёв данных композиция приобретает многослойный характер.
const landUse = turf.featureCollection([...]);
const population = turf.featureCollection([...]);
const landBuffer = turf.buffer(landUse, 1, { units: "kilometers" });
const overlap = turf.intersect(
turf.union(...landBuffer.features),
turf.convex(population)
);
Здесь объединяются разные типы географических данных через последовательные преобразования и агрегирование.
В сложных системах композиция операций принимает форму графа, а не линейной цепочки:
Пример логической структуры:
input
├─ buffer ─┬─ dissolve ─┐
│ │ │
│ └─ simplify ├─ union ─ output
└─ bbox ---------------─┘
Такой подход позволяет масштабировать геоаналитику на уровне архитектуры.
При последовательном применении операций накапливаются погрешности координат. Для контроля используются промежуточные нормализации:
const safePipeline = (fc) => {
const truncated = turf.truncate(fc, { precision: 6 });
const cleaned = turf.cleanCoords(truncated);
const simplified = turf.simplify(cleaned, { tolerance: 0.01 });
return simplified;
};
Композиция в этом контексте включает не только геооперации, но и операции стабилизации данных.
На практике выделяются устойчивые паттерны:
1. Map-buffer-reduce
2. Filter-transform-analyze
3. Normalize-analyze-project
Геоалгоритмы в Turf.js редко сводятся к одной функции. Почти всегда они представляют собой цепочку взаимосвязанных преобразований, где:
Эта модель делает библиотеку пригодной для построения сложных геоинформационных систем без введения внешнего состояния или императивных структур управления.