Фильтрация коллекций

В геоанализе работа ведётся не с одиночными объектами, а с наборами геометрий, оформленных как FeatureCollection. В рамках Turf.js фильтрация коллекций строится вокруг трёх типов операций:

  • пространственные предикаты (геометрические отношения)
  • атрибутивные фильтры (работа с properties)
  • итеративные проходы по коллекциям с формированием новых наборов

Структурно коллекция имеет вид:

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "geometry": { ... },
      "properties": { ... }
    }
  ]
}

Фильтрация всегда сводится к созданию новой FeatureCollection, так как исходные данные считаются неизменяемыми.


Итерация как основа фильтрации

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

featureEach

Позволяет обработать каждый объект коллекции:

import { featureEach } from "@turf/meta";

featureEach(points, (feature, index) => {
  console.log(index, feature.properties);
});

Используется как фундамент для любых пользовательских фильтров.


coordEach

Применяется для анализа координат внутри геометрий:

import { coordEach } from "@turf/meta";

coordEach(polygon, (coord) => {
  console.log(coord);
});

Подходит для низкоуровневой геометрической фильтрации, например:

  • удаление точек вне диапазона
  • проверка валидности координат
  • поиск экстремальных значений

propEach

Работа только с атрибутами:

import { propEach } from "@turf/meta";

propEach(collection, (properties) => {
  console.log(properties.type);
});

Используется для быстрой фильтрации без геометрических вычислений.


Атрибутивная фильтрация коллекций

Атрибутивные фильтры строятся поверх стандартного массива features.

Фильтрация по свойствам

const filtered = {
  type: "FeatureCollection",
  features: collection.features.filter(f =>
    f.properties.population > 100000
  )
};

Типовые сценарии:

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

Комбинированные условия

const filtered = {
  type: "FeatureCollection",
  features: collection.features.filter(f =>
    f.properties.type === "park" &&
    f.properties.area > 5000
  )
};

Пространственная фильтрация

Пространственная фильтрация — ключевая особенность Turf.js, основанная на геометрических предикатах.


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

import booleanPointInPolygon from "@turf/boolean-point-in-polygon";

const filtered = {
  type: "FeatureCollection",
  features: points.features.filter(point =>
    booleanPointInPolygon(point, polygon)
  )
};

Используется для:

  • поиска объектов внутри административных границ
  • сегментации данных по зонам
  • пространственной агрегации

Пересечение и исключение

Пересечение

import booleanIntersects from "@turf/boolean-intersects";

const filtered = lines.features.filter(line =>
  booleanIntersects(line, polygon)
);

Полное исключение (disjoint)

import booleanDisjoint from "@turf/boolean-disjoint";

const filtered = points.features.filter(point =>
  booleanDisjoint(point, polygon)
);

Разделение на:

  • объекты внутри зоны
  • объекты пересекающие границу
  • полностью внешние объекты

Внутри/снаружи для сложных геометрий

import booleanWithin from "@turf/boolean-within";

const filtered = points.features.filter(point =>
  booleanWithin(point, polygon)
);

Используется для строгой проверки вложенности геометрий.


Фильтрация через bbox (ограничивающий прямоугольник)

Один из самых быстрых способов предварительного отбора — проверка bounding box.

import bbox from "@turf/bbox";
import booleanPointInPolygon from "@turf/boolean-point-in-polygon";

const box = bbox(polygon);

const filtered = points.features.filter(p => {
  const [x, y] = p.geometry.coordinates;
  return (
    x >= box[0] &&
    x <= box[2] &&
    y >= box[1] &&
    y <= box[3]
  );
});

Преимущество:

  • минимальная вычислительная стоимость
  • быстрый предварительный отбор перед точной геометрией

Пространственная фильтрация через маскирование

Маскирование применяется, когда нужно обрезать или ограничить геометрию по области.

import mask from "@turf/mask";

const result = mask(points, polygon);

Используется для:

  • обрезки данных по границам регионов
  • подготовки визуализаций
  • геопространственной сегментации

Каскадная фильтрация (pipeline)

Фильтрация часто строится как цепочка шагов:

const result = {
  type: "FeatureCollection",
  features: points.features
    .filter(p => p.properties.type === "school")
    .filter(p => p.properties.students > 500)
    .filter(p => booleanPointInPolygon(p, district))
};

Характерные этапы:

  1. атрибутивный отбор (дешёвые операции)
  2. bbox-фильтрация (предварительное сокращение)
  3. точная геометрическая проверка

Геометрическая сегрегация наборов данных

Разделение коллекции на несколько групп:

const inside = [];
const outside = [];

points.features.forEach(p => {
  if (booleanPointInPolygon(p, polygon)) {
    inside.push(p);
  } else {
    outside.push(p);
  }
});

Результат:

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

Фильтрация линий и полигонов

Линии внутри зоны

const insideLines = lines.features.filter(line =>
  booleanWithin(line, polygon)
);

Линии, пересекающие границу

const crossingLines = lines.features.filter(line =>
  booleanIntersects(line, polygon)
);

Сложные предикаты и композиция условий

Комбинация пространственных и атрибутивных условий:

const result = {
  type: "FeatureCollection",
  features: collection.features.filter(f =>
    f.properties.category === "road" &&
    booleanIntersects(f, boundaryPolygon) &&
    f.properties.length > 1000
  )
};

Типовые сценарии:

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

Производительность фильтрации

При работе с большими коллекциями критичны следующие принципы:

1. Сначала атрибуты, потом геометрия

Атрибутивные проверки дешевле:

features.filter(f => f.properties.active)

2. Использование bbox как первого этапа

Сокращает количество дорогих проверок:

  • до 80–95% объектов может быть отсечено заранее

3. Избегание повторных вычислений

Плохой подход:

features.filter(f => booleanPointInPolygon(f, poly))
features.filter(f => booleanPointInPolygon(f, poly))

Правильный:

const precomputed = features.filter(f =>
  booleanPointInPolygon(f, poly)
);

Работа с вложенными коллекциями

Иногда фильтрация требуется внутри структур:

const result = geojson.features
  .map(layer => ({
    ...layer,
    features: layer.features.filter(f =>
      f.properties.value > 10
    )
  }));

Используется в:

  • многоуровневых GIS-структурах
  • тематических слоях
  • временных срезах данных

Использование пространственных индексов (концептуально)

При больших наборах данных фильтрация через перебор становится неэффективной. В таких случаях используется предварительная индексация (например, R-tree), поверх которой Turf.js применяет предикаты.

Типичный паттерн:

  1. индекс по bbox
  2. предварительный отбор кандидатов
  3. точная проверка через Turf-предикаты

Итоговая модель фильтрации

Фильтрация коллекций в Turf.js всегда строится как композиция:

  • итерация (featureEach, filter)
  • атрибуты (properties)
  • геометрические предикаты (boolean*)
  • предварительные ограничения (bbox)
  • разбиение и реконструкция FeatureCollection

Такая структура обеспечивает предсказуемость, масштабируемость и совместимость с геопространственными вычислениями любого уровня сложности