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

Иерархические визуализации в Nivo строятся вокруг строгого расчёта координат узлов, где каждая вершина дерева получает позицию на плоскости в зависимости от выбранного направления раскладки и параметров компоновки. Ориентация дерева определяет базовую систему координат, а алгоритм позиционирования узлов отвечает за распределение пространства между уровнями и соседними элементами.


В Nivo для деревьев используется параметр layout, который задаёт направление роста структуры. От него зависит, как интерпретируются координаты x и y каждого узла.

Вертикальная ориентация (top-to-bottom)

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

  • уровень глубины → координата Y
  • порядок среди соседей → координата X

Такая схема часто применяется для классических организационных диаграмм.

import { ResponsiveTree } from '@nivo/tree'

const data = {
    id: 'root',
    children: [
        { id: 'A' },
        { id: 'B' }
    ]
}

const TreeChart = () => (
    <ResponsiveTree
        data={data}
        identity="id"
        layout="vertical"
        nodeSize={{ x: 140, y: 60 }}
    />
)

Внутри алгоритма:

  • глубина увеличивает смещение вниз
  • ширина уровня распределяется между соседними узлами

Горизонтальная ориентация (left-to-right)

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

  • уровень глубины → координата X
  • порядок узлов → координата Y
<ResponsiveTree
    data={data}
    identity="id"
    layout="horizontal"
    nodeSize={{ x: 160, y: 80 }}
/>

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


Обратные направления (bottom-to-top, right-to-left)

Некоторые реализации Nivo поддерживают инвертированные направления:

  • bottom-to-top — рост вверх
  • right-to-left — рост влево

Эти варианты не меняют структуру данных, но инвертируют систему координат:

  • знак смещения по осям изменяется
  • корневой узел фиксируется на противоположной стороне

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

Позиционирование строится на основе модифицированного дерева Рейнгольда–Тилфорда или аналогичных иерархических алгоритмов.

Основные этапы:

1. Вычисление глубины

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

depth(root) = 0
depth(child) = depth(parent) + 1

Глубина напрямую влияет на координату основной оси.


2. Разделение поддеревьев

Каждое поддерево получает собственный сегмент пространства. Ширина сегмента зависит от количества листьев:

  • чем больше потомков — тем шире область
  • чем меньше — тем плотнее группировка

3. Центрирование родительских узлов

После распределения листьев выполняется обратный проход:

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

Это предотвращает перекосы структуры в одну сторону.


4. Расчёт координат

Для вертикальной ориентации:

x = horizontalPosition(node)
y = depth(node) * levelHeight

Для горизонтальной:

x = depth(node) * levelWidth
y = verticalPosition(node)

Node size и контроль расстояний

Параметр nodeSize определяет базовый шаг между узлами:

nodeSize={{ x: 180, y: 90 }}
  • x — горизонтальный интервал между соседями
  • y — вертикальный интервал между уровнями

Увеличение значений:

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

Separation: контроль плотности поддеревьев

Механизм separation управляет дополнительным расстоянием между узлами одного уровня.

Функция имеет вид:

separation={(a, b) => a.parent === b.parent ? 1 : 2}

Логика:

  • одинаковый родитель → минимальный зазор
  • разные ветви → увеличенный интервал

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


Рёбра (links) строятся на основе координат узлов. При смене ориентации меняется форма кривых:

Вертикальная схема

  • линии преимущественно вертикальные
  • используется сглаживание Bézier
  • контрольные точки смещаются по X

Горизонтальная схема

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

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


Радиальная ориентация и полярные координаты

Отдельный режим — radial layout — использует полярные координаты:

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

Преобразование:

x = r * cos(θ)
y = r * sin(θ)

Радиальная модель используется для компактного отображения больших деревьев.


Корневой узел и центрирование композиции

Позиция корня задаёт систему отсчёта всей структуры:

  • в вертикальном layout он фиксируется сверху
  • в горизонтальном — слева
  • в radial — в центре

Центрирование выполняется через смещение всего графа после первичного расчёта координат.


Масштабирование пространства и viewport

После вычисления позиций применяется нормализация:

  • вычисляются минимальные и максимальные координаты
  • добавляются margins
  • происходит fit-to-container

Это обеспечивает корректное отображение вне зависимости от размера контейнера.


Выравнивание узлов внутри уровня

На одном уровне узлы могут выравниваться:

  • по центру уровня
  • по верхней/нижней границе (для vertical)
  • по левой/правой границе (для horizontal)

Выравнивание влияет на симметрию дерева, особенно при неравномерных ветвлениях.


Плотность дерева и влияние структуры данных

Характер исходного графа напрямую влияет на итоговую геометрию:

  • сбалансированные деревья → равномерная сетка
  • линейные цепочки → вытянутая структура
  • сильно разветвлённые узлы → широкие «веера»

Алгоритм позиционирования не изменяет структуру, а лишь оптимизирует её отображение.


Смещение узлов и корректировка коллизий

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

  • обнаружение перекрытия bounding box
  • сдвиг поддеревьев на фиксированный шаг
  • перерасчёт координат для сохранения связей

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


Итоговая модель координат

Внутреннее представление каждого узла включает:

  • x, y — экранные координаты
  • depth — уровень вложенности
  • parent — ссылка на родителя
  • treePath — путь от корня

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