Автоматическое вычисление кривых

В Two.js кривые представляют собой последовательность опорных точек (вершин), между которыми библиотека автоматически вычисляет плавные переходы. Это достигается за счёт встроенной системы интерполяции, которая преобразует набор дискретных точек в непрерывную геометрическую форму.

Ключевым элементом является объект Two.Path, содержащий массив вершин (vertices). Каждая вершина может включать дополнительные управляющие параметры, позволяющие формировать кривизну сегмента.

const path = new Two.Path([
  new Two.Anchor(0, 0),
  new Two.Anchor(100, 50),
  new Two.Anchor(200, 0)
], true);

Параметр true указывает, что путь должен быть замкнутым.


Структура вершины и управляющих точек

Каждая вершина (Two.Anchor) содержит:

  • координаты: x, y
  • левый и правый управляющие векторы: controls.left, controls.right
  • флаг кривизны: command

По умолчанию Two.js автоматически рассчитывает управляющие точки, если вершины заданы без них. Это позволяет быстро создавать сглаженные линии без ручной настройки.

const anchor = new Two.Anchor(100, 100);

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

anchor.controls.left.set(-20, 0);
anchor.controls.right.set(20, 0);

Автоматическая интерполяция кривых

Two.js использует алгоритмы сглаживания, аналогичные кривым Безье. При включённом флаге curved библиотека:

  1. Анализирует соседние вершины
  2. Вычисляет направления касательных
  3. Определяет длину управляющих векторов
  4. Строит плавный переход между сегментами
path.curved = true;

В этом режиме:

  • вершины соединяются плавными кривыми
  • управляющие точки рассчитываются автоматически
  • сохраняется непрерывность первой производной (гладкость)

Алгоритм вычисления сглаживания

Автоматическое вычисление основано на следующих принципах:

1. Определение касательных

Для каждой вершины вычисляется вектор направления:

tangent = nextVertex - previousVertex

Этот вектор нормализуется и используется как основа для управляющих точек.

2. Расчёт управляющих точек

Длина управляющих векторов пропорциональна расстоянию между соседними вершинами:

controlLength = distance * smoothingFactor

Затем:

  • левая контрольная точка направлена к предыдущей вершине
  • правая — к следующей

3. Симметрия

Для гладкой кривой используется симметрия:

controls.left = -controls.right

Это обеспечивает плавность без изломов.


Параметры сглаживания

Two.js не предоставляет явного параметра “жёсткости” кривой, однако поведение можно контролировать косвенно:

Расстояние между вершинами

Чем ближе точки — тем более резкая кривая.

Положение вершин

Резкие углы создают более выраженные изгибы.

Ручная корректировка контролов

Позволяет переопределить автоматическое поведение.


Ручное и автоматическое управление

Two.js допускает смешанный режим:

  • часть вершин — автоматические
  • часть — с ручными управляющими точками
const a = new Two.Anchor(0, 0);
const b = new Two.Anchor(100, 100);
b.controls.left.set(-50, 0);
b.controls.right.set(50, 0);

const c = new Two.Anchor(200, 0);

const path = new Two.Path([a, b, c]);
path.curved = true;

В этом случае:

  • вершина b использует ручные настройки
  • остальные — автоматически сглаживаются

Замкнутые кривые

При замыкании пути (closed = true) алгоритм учитывает циклическую структуру:

  • первая вершина соединяется с последней
  • касательные рассчитываются с учётом замыкания
path.closed = true;

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

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

Динамическое обновление кривых

Two.js автоматически пересчитывает кривые при изменении вершин:

path.vertices[1].x += 10;
path.vertices[1].y += 20;

После изменения:

  • пересчитываются управляющие точки
  • обновляется геометрия
  • выполняется перерисовка

При использовании анимации это позволяет создавать плавные морфинги форм.


Анимация кривых

Изменяя координаты вершин во времени, можно получать динамические эффекты:

two.bind('upd ate', function() {
  path.vertices.forEach((v, i) => {
    v.y += Math.sin(Date.now() * 0.001 + i) * 0.5;
  });
});

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

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

Управление резкостью кривой

Чтобы уменьшить сглаживание:

Способ 1: отключение кривизны

path.curved = false;

Способ 2: дублирование вершин

Создание дополнительных точек уменьшает плавность:

new Two.Anchor(100, 100),
new Two.Anchor(105, 102),
new Two.Anchor(110, 100)

Способ 3: ручные контролы

Явное задание коротких управляющих векторов:

anchor.controls.left.se t(-5, 0);
anchor.controls.right.set(5, 0);

Производительность и оптимизация

Автоматическое вычисление кривых требует дополнительных ресурсов:

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

Рекомендации:

  • минимизировать количество вершин
  • избегать частых изменений в больших путях
  • использовать curved = false, если сглаживание не требуется

Визуализация управляющих точек

Для отладки полезно отображать контролы:

path.vertices.forEach(v => {
  const left = two.makeCircle(
    v.x + v.controls.left.x,
    v.y + v.controls.left.y,
    3
  );

  const right = two.makeCircle(
    v.x + v.controls.right.x,
    v.y + v.controls.right.y,
    3
  );

  left.fill = 'red';
  right.fill = 'blue';
});

Это позволяет:

  • понять форму кривой
  • корректировать поведение
  • выявлять аномалии

Особенности алгоритма Two.js

  • Используется локальное сглаживание (учёт соседних точек)
  • Нет глобальной оптимизации всей кривой
  • Управляющие точки пересчитываются при каждом обновлении
  • Система ориентирована на интерактивную графику, а не точную геометрию

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

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

Для сложных задач рекомендуется:

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

Практическое применение

Автоматическое вычисление кривых используется для:

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

Пример волнообразной линии:

const points = [];

for (let i = 0; i < 20; i++) {
  points.push(new Two.Anchor(i * 20, 200));
}

const wave = new Two.Path(points, false);
wave.curved = true;

two.bind('update', function() {
  wave.vertices.forEach((v, i) => {
    v.y = 200 + Math.sin(i + Date.now() * 0.002) * 20;
  });
});

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


Взаимодействие с другими примитивами

Кривые могут комбинироваться с:

  • группами (Two.Group)
  • масками
  • градиентами
  • трансформациями

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


Внутренняя логика пересчёта

При изменении пути:

  1. Обновляются вершины
  2. Пересчитываются управляющие точки (если curved = true)
  3. Обновляется список сегментов
  4. Генерируется SVG-путь или canvas-команды

Это происходит автоматически при каждом кадре, если сцена активна.


Контроль поведения через свойства

Основные свойства:

path.curved = true;
path.closed = false;
path.automatic = true;
  • curved — включает сглаживание
  • closed — замыкает путь
  • automatic — управляет автоматическим пересчётом контролов

Отключение автоматического режима:

path.automatic = false;

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


Комбинирование сегментов разного типа

В одном пути могут сочетаться:

  • прямые линии
  • кривые сегменты

Это достигается через настройку отдельных вершин:

anchor.command = Two.Commands.line;

или

anchor.command = Two.Commands.curve;

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


Вывод поведения системы

Автоматическое вычисление кривых в Two.js представляет собой баланс между простотой и гибкостью:

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

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