Кривые (curves): curveBasis, curveCardinal, curveCatmullRom, curveStep и другие

В D3.js форма линии, построенной через d3.line(), определяется не только набором точек, но и способом интерполяции между ними. Именно кривые (curve functions) отвечают за то, как именно соединяются точки: прямыми отрезками, сглаженными сплайнами, ступенчатыми переходами или специальными математическими интерполяциями.

Каждая кривая в D3 представляет собой функцию, которая передаётся в генератор линии:

d3.line()
  .curve(d3.curveBasis);

Кривая не изменяет данные, а управляет алгоритмом построения SVG-пути (d атрибут).


Архитектура кривых в D3

Кривые в D3 реализуют интерфейс curve factory, который определяет методы:

  • lineStart() — начало новой линии
  • lineEnd() — завершение линии
  • point(x, y) — добавление точки
  • areaStart() / areaEnd() — для областей (area generator)
  • curve() — внутренние вычисления интерполяции

Каждая кривая решает одну задачу: как интерполировать последовательность точек в плавную или дискретную форму.


Линейная кривая: curveLinear

Базовая форма без сглаживания:

d3.line()
  .curve(d3.curveLinear);

Поведение

  • Точки соединяются прямыми отрезками
  • Отсутствует интерполяция
  • Максимальная точность исходных данных

Использование

  • Графики с дискретными значениями
  • Геометрические построения
  • Отладка данных

Ступенчатые кривые: curveStep

Ступенчатая интерполяция создаёт «ломаную лестницу».

curveStep

d3.line()
  .curve(d3.curveStep);

Форма:

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

curveStepBefore

d3.line()
  .curve(d3.curveStepBefore);

Изменение порядка:

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

curveStepAfter

d3.line()
  .curve(d3.curveStepAfter);
  • сначала горизонталь
  • затем вертикальный переход

Особенности ступенчатых кривых

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

Сглаженные сплайны: curveBasis

Кривая B-spline обеспечивает мягкое сглаживание без прохождения через все точки.

d3.line()
  .curve(d3.curveBasis);

Свойства

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

Поведение

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

Применение

  • визуализация трендов
  • сглаживание шумных данных
  • эстетические графики

Важная особенность

Кривая может визуально «сдвигать» экстремумы относительно исходных значений.


curveBasisClosed и curveBasisOpen

curveBasisClosed

Замыкает кривую в кольцо:

d3.line()
  .curve(d3.curveBasisClosed);
  • последняя точка соединяется с первой
  • используется в полярных диаграммах и замкнутых формах

curveBasisOpen

d3.line()
  .curve(d3.curveBasisOpen);
  • открытая форма без замыкания
  • более контролируемое сглаживание на краях

curveCardinal: контролируемое сглаживание

Cardinal spline даёт баланс между точностью и сглаживанием.

d3.line()
  .curve(d3.curveCardinal);

Параметр tension

d3.curveCardinal.tension(0.5);
  • tension = 0 → сильное сглаживание
  • tension → 1 → приближение к линейной форме

Особенности

  • кривая проходит через все точки
  • сглаживание управляется натяжением
  • возможны небольшие «перерегулирования»

Использование

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

curveCardinalClosed и curveCardinalOpen

curveCardinalClosed

d3.curveCardinalClosed
  • замкнутая форма
  • полезна для круговых диаграмм и циклических данных

curveCardinalOpen

d3.curveCardinalOpen
  • открытая форма с контролем краевых сегментов
  • предотвращает резкие артефакты на концах линии

curveCatmullRom: интерполяция через точки

Catmull-Rom spline — одна из наиболее используемых кривых в D3 для гладких линий, проходящих через все точки.

d3.line()
  .curve(d3.curveCatmullRom);

Параметр alpha

d3.curveCatmullRom.alpha(0.5);

Режимы поведения alpha

  • alpha = 0 — uniform (равномерная интерполяция)
  • alpha = 0.5 — centripetal (наиболее стабильная форма)
  • alpha = 1 — chordal (более «резкая» геометрия)

Особенности

  • линия проходит через все точки
  • минимизирует резкие перегибы
  • более предсказуема, чем Cardinal

Использование

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

curveCatmullRomClosed и curveCatmullRomOpen

curveCatmullRomClosed

d3.curveCatmullRomClosed
  • формирует замкнутую интерполяцию
  • используется для циклических структур

curveCatmullRomOpen

d3.curveCatmullRomOpen
  • открытая форма
  • корректное поведение на концах без фиктивных точек

curveMonotoneX и curveMonotoneY

Монотонные кривые предотвращают появление локальных экстремумов.

curveMonotoneX

d3.line()
  .curve(d3.curveMonotoneX);
  • сохраняет монотонность по оси X
  • исключает «петли»

curveMonotoneY

d3.line()
  .curve(d3.curveMonotoneY);
  • сохраняет монотонность по Y

Особенности

  • гарантируют отсутствие артефактных перегибов
  • подходят для строгих научных графиков
  • не всегда выглядят максимально «гладко», но математически корректны

curveNatural: естественная интерполяция

d3.line()
  .curve(d3.curveNatural);

Поведение

  • имитирует физически естественное движение
  • сглаживание основано на внутренней аппроксимации

Характеристики

  • мягкие переходы
  • визуально «органические» линии
  • не гарантирует прохождение через точки с высокой точностью

curveBundle: сглаживание графовых структур

d3.line()
  .curve(d3.curveBundle.beta(0.8));

Параметр beta

  • низкое значение → сильное сглаживание
  • высокое значение → ближе к прямым линиям

Использование

  • иерархические структуры
  • визуализация графов
  • маршруты связей

Особенность

Кривая работает лучше всего в связке с d3.hierarchy и edge bundling техниками.


curveLinearClosed

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

Сравнение поведения основных кривых

Без сглаживания

  • curveLinear
  • curveStep

Мягкое сглаживание

  • curveBasis
  • curveNatural

Контролируемое сглаживание через точки

  • curveCatmullRom
  • curveCardinal

Строгая геометрическая устойчивость

  • curveMonotoneX
  • curveMonotoneY

Специальные структуры

  • curveBundle

Влияние кривой на SVG path

Каждая кривая влияет на структуру атрибута d:

  • количество сегментов
  • наличие контрольных точек Bézier
  • плавность переходов
  • плотность команд C, L, S

Например:

  • curveLinear → только L
  • curveBasis → множество кубических Bézier (C)
  • curveStep → чередование H и V логики

Комбинирование кривых с генераторами

Кривые применяются не только к line, но и к:

  • d3.area()
  • d3.radialLine()
  • d3.linkHorizontal() / linkVertical()
d3.area()
  .curve(d3.curveCatmullRom);

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


Производительность и поведение на больших наборах данных

  • curveLinear — минимальная нагрузка
  • curveStep — низкая сложность
  • curveBasis — умеренная нагрузка
  • curveCatmullRom — более затратная интерполяция
  • curveBundle — может быть вычислительно тяжёлой при больших графах

Оптимизация часто достигается выбором более простой кривой при высокой плотности точек.


Практика выбора кривой по типу данных

  • финансовые данные с шумом → curveCardinal или curveCatmullRom
  • строгие измерения → curveLinear или curveMonotoneX
  • событийные временные ряды → curveStep
  • визуализация трендов → curveBasis
  • графовые структуры → curveBundle