Силы: forceLink, forceManyBody, forceCenter, forceCollide, forceX, forceY

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

Основная сущность — симуляция, к которой подключаются силы:

const simulation = d3.forceSimulation(nodes);

Каждая сила добавляется через:

simulation.force("name", d3.forceX(...));

Система работает итеративно: на каждом тике пересчитываются взаимодействия между узлами и внешними полями.


forceCenter: фиксация системы в центре

Сила forceCenter задаёт точку притяжения, к которой стремится вся система. Она не фиксирует узлы жёстко, а создаёт мягкое смещение координат, стабилизируя граф в пределах заданной области.

d3.forceCenter(width / 2, height / 2)

Механика работы

Каждый узел получает корректировку координат:

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

Особенности применения

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

forceCenter не учитывает массу узлов и не формирует локальные структуры.


forceManyBody: глобальные взаимодействия узлов

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

d3.forceManyBody()
  .strength(-50)

Параметр strength

  • отрицательные значения — отталкивание
  • положительные — притяжение

Принцип вычисления

Для каждого узла:

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

Оптимизация

Полная сложность (O(n^2)) заменяется приближёнными алгоритмами (например, квадродерево Barnes–Hut), что позволяет работать с большими графами.

Поведение системы

  • отрицательная сила создаёт равномерное распределение узлов
  • положительная — кластеризацию и слипание

forceLink формирует ограничения между узлами, задавая «ребра» графа как пружины.

d3.forceLink(links)
  .id(d => d.id)
  .distance(80)
  .strength(1)

Принцип действия

Каждая связь между двумя узлами рассматривается как пружина:

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

Основные параметры

distance

Определяет желаемое расстояние между связанными узлами.

strength

Регулирует жёсткость связи:

  • высокие значения — жёсткая структура
  • низкие — гибкие, растяжимые связи

Идентификация узлов

Метод id() задаёт способ сопоставления ссылок:

.id(d => d.id)

Это необходимо при работе с объектами ссылок вида:

{ source: "A", target: "B" }

Поведение в графе

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

forceCollide: предотвращение пересечений

forceCollide вводит радиусную модель узлов, предотвращая наложение элементов.

d3.forceCollide()
  .radius(10)

Алгоритм работы

Каждый узел рассматривается как окружность:

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

Параметр radius

Может задаваться как функция:

.radius(d => d.size)

Особенности

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

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

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


forceX: горизонтальное поле притяжения

forceX создаёт направленное поле вдоль оси X, притягивая узлы к заданным координатам.

d3.forceX(width / 2)
  .strength(0.1)

Механика

Для каждого узла:

  • вычисляется разница между x-координатой и целевой линией
  • применяется пропорциональное ускорение

Применение

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

Влияние strength

  • низкие значения — мягкое выравнивание
  • высокие — почти фиксированная позиция по X

forceY: вертикальное поле притяжения

forceY аналогичен forceX, но действует вдоль оси Y.

d3.forceY(height / 2)
  .strength(0.1)

Принцип работы

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

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

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

Взаимодействие сил в одной симуляции

Силы D3 не работают изолированно. Поведение системы определяется их суммарным влиянием.

Конфликтующие воздействия

  • forceManyBody раздвигает узлы
  • forceLink фиксирует расстояния
  • forceCenter стабилизирует всю систему
  • forceCollide устраняет пересечения
  • forceX и forceY формируют глобальную геометрию

Пример композиции

const simulation = d3.forceSimulation(nodes)
  .force("link", d3.forceLink(links).id(d => d.id).distance(80))
  .force("charge", d3.forceManyBody().strength(-40))
  .force("center", d3.forceCenter(width / 2, height / 2))
  .force("collision", d3.forceCollide().radius(12))
  .force("x", d3.forceX(width / 2).strength(0.05))
  .force("y", d3.forceY(height / 2).strength(0.05));

Балансировка системы

Стабильность достигается подбором параметров:

  • слишком сильный manyBody разрушает связи
  • слишком сильный link подавляет структуру
  • collision может замедлить схождение системы
  • x и y формируют глобальную сетку, но могут «перетянуть» граф

Математическая модель обновления состояния

На каждом тике симуляции выполняется:

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

Упрощённо:

[ v = v + a t] [ x = x + v t]

Где ускорение формируется суммой всех активных сил.


Роль охлаждения (alpha)

Симуляция использует параметр затухания энергии:

  • высокая alpha — хаотичное движение
  • низкая alpha — стабилизация системы

Каждый тик:

[ _{t+1} = _t decay]

Когда alpha становится ниже порога, симуляция останавливается.


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

Радиальная структура

Комбинация forceCenter + forceManyBody + forceCollide:

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

Линейные диаграммы

Комбинация forceX или forceY с forceLink:

  • один вектор фиксирует ось
  • связи формируют локальную структуру

Кластеризация

Усиленный forceManyBody с умеренными связями:

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

Поведение системы при увеличении количества узлов

При росте числа элементов:

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

Сложные графы требуют уменьшения жёсткости связей и увеличения затухания alpha для устойчивости.


Синхронизация с визуализацией

Силовая симуляция обычно привязывается к отрисовке:

simulation.on("tick", () => {
  node
    .attr("cx", d => d.x)
    .attr("cy", d => d.y);
});

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


Геометрическая интерпретация

Силовая модель формирует непрерывное многомерное поле:

  • forceCenter — точка минимума потенциальной энергии
  • forceManyBody — поле взаимодействия частиц
  • forceLink — ограниченные потенциалы между парами
  • forceCollide — барьерные функции
  • forceX, forceY — линейные потенциальные градиенты

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