Подібно до графа, цей фреймворк містить дані у вигляді вузлів і ребер. Одне зауваження: у термінології редактора, ребра графа відомі як з’єднання.
Екземпляр NodeEditor
зберігає ці дані в нормалізованому форматі, зокрема у вигляді двох окремих списків, що містять об’єкти такого типу:
{ id: <string> }
для вузлів{ id: <string>, source: <string>, target: <string> }
для з’єднаньІніціалізація редактора передбачає використання базової схеми без будь-яких додаткових полів для початку:
import { NodeEditor, BaseSchemes, getUID } from 'rete'
const editor = new NodeEditor<BaseSchemes>()
Маючи справу з даними графа, у вас є можливість створювати довільні ідентифікатори для вузлів і з’єднань або використовувати існуючі.
const a = { id: getUID() }
const b = { id: getUID() }
const connection = { id: getUID(), source: a.id, target: b.id }
await editor.addNode(a)
await editor.addNode(b)
await editor.addConnection(connection)
Тепер ми можемо отримати список щойно доданих вузлів і з’єднань
editor.getNodes() // returns [a, b]
editor.getConnections() // returns [connection]
У вас є всі необхідні методи для обробки графу, такі як отримання списку вхідних з’єднань або всіх вхідних вузлів, які ми обговоримо в наступних розділах.
Наступний код показує, як отримати список вхідних і вихідних з’єднань для node
:
const connections = editor.getConnections()
const incomingConnections = connections.filter(connection => connection.target === node.id)
const outgoingConnections = connections.filter(connection => connection.source === node.id)
Ми можемо використовувати змінні з попереднього розділу для отримання вхідних або вихідних вузлів:
const incomers = incomingConnections.map(connection => editor.getNode(connection.source))
const outgoers = outgoingConnections.map(connection => editor.getNode(connection.target))
Взагалі-то цього достатньо для простих випадків, але якщо між вузлами існує більше одного з’єднання, нам доведеться видалити дублікати:
Array.from(new Set(incomers))
Array.from(new Set(outgoers))
Зазначені вище підходи досить гнучкі, але вимагають самостійної імплементації більш складних методів. На щастя, пакет rete-structures
пропонує такі методи, розділені на 4 категорії:
Встановимо залежність
npm i rete-structures
Використовуйте наступний оператор імпорту та декларацію
import { structures } from 'rete-structures'
const graph = structures(editor)
graph.nodes()
graph.connections()
Існують інші методи graph
, які служать різним цілям, продемонстровані нижче з кодом та інтерактивним превью. Отримані вузли помітні, а попередній перегляд дозволяє користувачам вибирати вузли та спостерігати за змінами.
Виконання будь-якого з методів зазвичай дає вузли, які не були відкинуті, а також їхні з’єднання, якщо обидва їхні вузли присутні.
Вузли без вхідних з'єднань відомі як кореневі вузли
structures(graph).roots()
Листові вузли – це вузли, які не мають вихідних з’єднань
structures(graph).leaves()
Вхідні вузли безпосередньо підключені до вибраного вузла
structures(graph).incomers(selectedNodeId)
Вихідні вузли безпосередньо підключені до вибраного вузла
structures(graph).outgoers(selectedNodeId)
Кожен вхідний вузол, а також його вхідні вузли тощо
structures(graph).predecessors(selectedNodeId)
Кожен вихідний вузол, а також його вихідні вузли тощо
structures(graph).successors(selectedNodeId)
Фільтрування можна застосовувати як до вузлів, так і до з’єднань
structures(graph).filter(Boolean, ({ source, target }) => source === selectedNodeId || target === selectedNodeId)
У наступних прикладах показано випадки, коли вибраний вузол служить другим графом
Об'єднання графа і вузла з цього графа дає той самий граф
structures(editor).union({ nodes: [selectedNode], connections: [] })
Віднімаючи вузол із графа, ви можете отримати новий графік без цього вузла
structures(editor).difference({ nodes: [selectedNode], connections: [] })
Перетинаючи граф із вузлом із цього графу, ви отримаєте новий граф, який включає лише вибраний вузол
structures(editor).intersection({ nodes: [selectedNode], connections: [] })
Ця категорія відноситься до графів, які містять вузли зі зв’язком «батько-дитина», зокрема вузли, у яких визначено поле parent
та вкладені в інші вузли.
Список прямих нащадків, а саме дітей
structures(editor).children((n) => n.id === selectedNodeId);
Список батьків
structures(editor).parents((n) => n.id === selectedNodeId);
Список усіх нащадків, включаючи дітей, онуків і наступні покоління
structures(editor).descendants((n) => n.id === selectedNodeId);
Список усіх предків, від батьків до прадідів і далі
structures(editor).ancestors((n) => n.id === selectedNodeId);
Вузли без указаної властивості parent
structures(editor).orphans();
Вузли, які мають спільного батька з вибраним вузлом, навіть якщо він не має батьків
structures(editor).siblings((n) => n.id === selectedNodeId)