import type { Graph } from '../runtime/graph';
import type { EdgeDirection, ElementType, ID } from '../types';
import { idOf } from './id';
import { bfs } from './traverse';
/**
* 获取指定元素在 n 度关系内的所有元素的 ID
*
* Get the IDs of all elements within an n-degree relationship from the specified element
* @remarks
* 对于节点,0 度关系是节点本身,1 度关系包括节点的直接相邻节点和边,以此类推。
* 对于边,0 度关系是边本身,1 度关系包括边本身及其两个端点,以此类推。
*
* For a node, 0-degree relationship includes the node itself; 1-degree relationship includes the node's direct neighbors and their connecting edges, etc.
* For an edge, 0-degree relationship includes the edge itself; 1-degree relationship includes the edge and its two endpoints, etc
* @param graph - 图实例 | graph instance
* @param elementType - 元素类型 | element type
* @param elementId - 起始元素的 ID | start element ID
* @param degree - 指定的度数 | the specified degree
* @param direction - 边的方向 | edge direction
* @returns - 返回节点和边的 ID 数组 | Returns an array of node and edge IDs
*/
export function getElementNthDegreeIds(
graph: Graph,
elementType: ElementType,
elementId: ID,
degree: number,
direction: EdgeDirection = 'both',
): ID[] {
if (elementType === 'combo' || elementType === 'node') {
return getNodeNthDegreeIds(graph, elementId, degree, direction);
}
const edgeData = graph.getEdgeData(elementId);
if (!edgeData) return [];
const sourceRelations = getNodeNthDegreeIds(graph, edgeData.source, degree - 1, direction);
const targetRelations = getNodeNthDegreeIds(graph, edgeData.target, degree - 1, direction);
return Array.from(new Set([...sourceRelations, ...targetRelations, elementId]));
}
/**
* 获取指定节点在 n 度关系内的所有元素的 ID
*
* Get all elements IDs within n-degree relationship of the specified node
* @remarks
* 节点的 0 度关系是节点本身,1 度关系是节点的直接相邻节点和边,以此类推
* @param direction
* 0-degree relationship of a node is the node itself; 1-degree relationship is the node's neighboring nodes and related edges, etc
* @param graph - 图实例 | graph instance
* @param startNodeId - 起始节点的 ID | The ID of the starting node
* @param degree - 指定的度数 | The specified degree
* @param direction - 边的方向 | The direction of the edge
* @returns - 返回节点和边的 ID 数组 | Returns an array of node and edge IDs
*/
export function getNodeNthDegreeIds(
graph: Graph,
startNodeId: ID,
degree: number,
direction: EdgeDirection = 'both',
): ID[] {
const visitedNodes = new Set();
const visitedEdges = new Set();
const relations = new Set();
bfs(
startNodeId,
(nodeId: ID, depth: number) => {
if (depth > degree) return;
relations.add(nodeId);
graph.getRelatedEdgesData(nodeId, direction).forEach((edge) => {
const edgeId = idOf(edge);
if (!visitedEdges.has(edgeId) && depth < degree) {
relations.add(edgeId);
visitedEdges.add(edgeId);
}
});
},
(nodeId: ID) => {
return graph
.getRelatedEdgesData(nodeId, direction)
.map((edge) => (edge.source === nodeId ? edge.target : edge.source))
.filter((neighborNodeId) => {
if (!visitedNodes.has(neighborNodeId)) {
visitedNodes.add(neighborNodeId);
return true;
}
return false;
});
},
);
return Array.from(relations);
}