Разделение линии на сегменты

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

Перед операциями разбиения линия в Turf.js обычно представляется как LineString:

import { lineString } from "@turf/helpers";

const line = lineString([
  [30.5, 50.5],
  [31.0, 50.6],
  [31.5, 50.4],
  [32.0, 50.7]
]);

Каждая пара координат образует вершину, а между ними формируются сегменты. Именно эти сегменты становятся базовой единицей при дальнейшем разбиении.

Сегментация по вершинам с lineToSegment-подобной логикой

В Turf.js отсутствует отдельная функция с названием lineToSegments, однако эквивалентная операция реализуется через lineSegment, которая преобразует линию в набор отдельных отрезков.

import { lineSegment } from "@turf/turf";

const segments = lineSegment(line);

Результатом является FeatureCollection, где каждый элемент — отдельный отрезок между двумя последовательными вершинами исходной линии.

Каждый сегмент имеет структуру:

{
  "type": "Feature",
  "geometry": {
    "type": "LineString",
    "coordinates": [
      [x1, y1],
      [x2, y2]
    ]
  }
}

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

Разбиение линии на равные части через lineChunk

Для деления линии на фрагменты фиксированной длины применяется lineChunk. Эта функция разбивает исходный LineString на отрезки заданной протяжённости с учётом геодезической длины.

import { lineChunk } from "@turf/turf";

const chunks = lineChunk(line, 5, { units: "kilometers" });

В данном случае линия будет разделена на сегменты по 5 километров каждый. Последний сегмент может быть короче заданного значения, если остаток длины не кратен шагу.

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

  • длина вычисляется по сферической модели Земли;
  • сегменты сохраняют порядок следования;
  • геометрия не упрощается, а именно разрезается;
  • результат всегда является набором LineString.

Контроль длины линии через turf.length

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

import { length } from "@turf/turf";

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

Это значение используется для расчёта количества сегментов и динамического выбора шага разбиения.

Пример вычисления количества сегментов:

const step = 2; // км
const count = Math.ceil(total / step);

Разбиение по точкам с lineSplit

Когда линия должна быть разделена по внешним геометрическим объектам (например, точкам пересечения или другой линии), используется lineSplit.

import { lineSplit, point } from "@turf/turf";

const splitter = point([31.0, 50.6]);

const result = lineSplit(line, splitter);

Также допускается использование линии в качестве разделителя:

const result = lineSplit(line, anotherLine);

Механизм работы:

  • вычисляются точки пересечения;
  • исходная линия разрезается в этих точках;
  • возвращается коллекция независимых отрезков.

Важно учитывать, что корректность результата зависит от наличия реального пересечения геометрий.

Разбиение по расстоянию вдоль линии через lineSliceAlong

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

genui{“math_block_widget_always_prefetch_v2”:{“content”:“d = ”}}

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

Пример:

import { lineSliceAlong } from "@turf/turf";

const part = lineSliceAlong(line, 2, 7, { units: "kilometers" });

Результат — подлиния между 2 и 7 километром вдоль исходной геометрии.

Особенности:

  • поддерживает отрицательные значения как смещение от конца;
  • сохраняет исходную топологию;
  • полезна для поэтапной навигации.

Построение равномерной сегментации через итеративное извлечение

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

import { lineSliceAlong, length } from "@turf/turf";

const step = 1; // км
const total = length(line, { units: "kilometers" });

let segments = [];

for (let i = 0; i < total; i += step) {
  const segment = lineSliceAlong(line, i, i + step, { units: "kilometers" });
  segments.push(segment);
}

Такой метод позволяет:

  • гарантировать одинаковую длину сегментов;
  • сохранять геометрическую непрерывность;
  • применять индивидуальные атрибуты к каждому участку.

Работа с атрибутивными данными при сегментации

При разбиении линии важен вопрос наследования свойств. В Turf.js свойства исходного объекта не всегда автоматически распределяются между сегментами.

При использовании lineSegment можно вручную переносить свойства:

const segments = lineSegment(line);

segments.features = segments.features.map((f, index) => {
  f.properties = {
    ...line.properties,
    segmentIndex: index
  };
  return f;
});

Это позволяет сохранять бизнес-логику на уровне отдельных участков маршрута.

Геометрические особенности и ограничения

При работе с разбиением линий необходимо учитывать несколько факторов:

  • при большом количестве вершин вычисления становятся более затратными;
  • геометрии в разных CRS не поддерживаются напрямую (только WGS84);
  • самопересекающиеся линии могут давать неожиданные результаты при split-операциях;
  • точность зависит от выбранной единицы измерения и модели Земли.

Комбинирование методов разбиения

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

  • lineSegment — для анализа структуры;
  • lineChunk — для грубой сегментации по длине;
  • lineSliceAlong — для точного контроля участков;
  • lineSplit — для геометрического разрезания по объектам.

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