В основе большинства операций в геопространственных вычислениях лежит
структура данных GeoJSON. В Turf.js работа почти всегда происходит не с
одиночными координатами, а с коллекциями объектов: Feature,
FeatureCollection, массивами геометрий и вложенными
структурами.
Коллекции в Turf.js требуют особого подхода к перебору, поскольку данные могут быть вложенными, неоднородными и содержать смешанные типы геометрий.
GeoJSON определяет несколько уровней группировки:
FeatureCollection — набор объектов
FeatureFeature — объект с геометрией и свойствамиGeometryCollection — набор геометрийКаждый уровень требует корректного способа обхода, иначе часть данных может быть пропущена.
Перебор в Turf.js строится вокруг унифицированного подхода:
Вместо прямого использования for по вложенным массивам
используются функции из модуля @turf/meta.
Функция featureEach используется для обхода всех
Feature внутри FeatureCollection.
import { featureEach } from "@turf/meta";
const collection = {
type: "FeatureCollection",
features: [
{ type: "Feature", geometry: { type: "Point", coordinates: [10, 20] }, properties: {} },
{ type: "Feature", geometry: { type: "Point", coordinates: [30, 40] }, properties: {} }
]
};
featureEach(collection, (currentFeature, featureIndex) => {
console.log(featureIndex, currentFeature.geometry);
});
Для работы непосредственно с координатами используется
coordEach.
import { coordEach } from "@turf/meta";
coordEach(collection, (currentCoord, coordIndex) => {
console.log(coordIndex, currentCoord);
});
Для Polygon:
{
type: "Polygon",
coordinates: [
[
[0, 0],
[10, 0],
[10, 10],
[0, 0]
]
]
}
coordEach последовательно вернёт каждую координату без
учёта колец.
propEach используется для перебора только свойства
properties каждого Feature.
import { propEach } from "@turf/meta";
propEach(collection, (properties, featureIndex) => {
console.log(featureIndex, properties);
});
Функция geomEach позволяет работать только с
геометриями, игнорируя свойства.
import { geomEach } from "@turf/meta";
geomEach(collection, (geometry, featureIndex) => {
console.log(featureIndex, geometry.type);
});
GeoJSON поддерживает мульти-геометрии:
flattenEach преобразует их в последовательность простых
геометрий.
import { flattenEach } from "@turf/meta";
flattenEach(collection, (currentFeature, featureIndex, multiFeatureIndex) => {
console.log(featureIndex, multiFeatureIndex, currentFeature.geometry.type);
});
При переборе коллекций важно учитывать несколько типов индексов:
featureIndex — индекс Feature в FeatureCollectioncoordIndex — глобальный индекс координатmultiFeatureIndex — индекс части мульти-геометрииЭти индексы не взаимозаменяемы и отражают разные уровни структуры данных.
GeoJSON допускает вложенность:
Каждый уровень требует отдельного подхода к обходу. Turf.js скрывает
рекурсию внутри meta-функций, обеспечивая единообразный
API.
При работе с коллекциями часто возникает необходимость трансформации данных.
Пример масштабирования координат:
import { coordEach } from "@turf/meta";
coordEach(collection, (coord) => {
coord[0] *= 2;
coord[1] *= 2;
});
Для предотвращения мутаций исходных данных используется копирование:
const cloned = JSON.parse(JSON.stringify(collection));
coordEach(cloned, (coord) => {
coord[0] += 1;
});
При этом сохраняется исходная структура GeoJSON.
При работе с большими коллекциями (десятки тысяч объектов) критичны следующие аспекты:
coordEach наиболее затратен по времениpropEach — наиболее лёгкийflattenEach добавляет накладные операции разбиенияОптимизация достигается выбором минимально необходимого уровня перебора.
Комбинации функций позволяют реализовать сложные сценарии анализа:
import { featureEach, coordEach } from "@turf/meta";
featureEach(collection, (feature) => {
coordEach(feature, (coord) => {
coord[2] = coord[2] || 0;
});
});
Здесь происходит переход от уровня Feature к уровню координат внутри каждой геометрии.
GeometryCollection требует особого внимания, так как:
geomEach или
coordEachПример:
const geometryCollection = {
type: "GeometryCollection",
geometries: [
{ type: "Point", coordinates: [0, 0] },
{ type: "LineString", coordinates: [[1, 1], [2, 2]] }
]
};
Внутри callback-функций можно реализовывать фильтрацию:
import { featureEach } from "@turf/meta";
const result = [];
featureEach(collection, (feature) => {
if (feature.geometry.type === "Point") {
result.push(feature);
}
});
Такой подход позволяет избегать дополнительного прохода по данным.
Большинство операций Turf.js — это надстройка над базовым перебором:
Все они в конечном счёте опираются на обход коллекций через
meta-функции.
Callback в функциях перебора имеет следующие свойства:
Сложные задачи часто требуют каскадного перебора:
import { featureEach, coordEach } from "@turf/meta";
featureEach(collection, (feature) => {
coordEach(feature, (coord) => {
coord[0] = Math.round(coord[0]);
coord[1] = Math.round(coord[1]);
});
});
Такой подход обеспечивает полный контроль над структурой данных на каждом уровне.