DB-GPT/web/utils/graph.ts
2024-09-03 10:28:59 +08:00

85 lines
2.7 KiB
TypeScript

import type { EdgeData, GraphData, ID } from '@antv/g6';
import { idOf } from '@antv/g6';
import { groupBy, pick } from 'lodash';
/**
* Reassign the layout style to the original graph data
* @param model - original graph data
* @param layoutResult - layout result
*/
export function reassignLayoutStyle(model: GraphData, layoutResult: GraphData) {
layoutResult.nodes?.forEach(layoutNode => {
const modelNode = model.nodes?.find(node => node.id === layoutNode.id);
if (modelNode?.style) Object.assign(modelNode.style || {}, pick(layoutNode.style, ['x', 'y', 'z']));
});
}
/**
* Calculate node size based on degree
* @param degree - degree of the node
* @param minSize - minimum size of the node
* @param maxSize - maximum size of the node
* @param minDegree - minimum degree
* @param maxDegree - maximum degree
* @returns size of the node
*/
export function getSize(degree: number, minSize = 24, maxSize = 60, minDegree = 1, maxDegree = 10): number {
const _degree = Math.max(minDegree, Math.min(maxDegree, degree));
const size = minSize + ((_degree - minDegree) / (maxDegree - minDegree)) * (maxSize - minSize);
return size;
}
/**
* Get node degree, means the number of edges connected to the node
* @param edges - all edges data
* @param nodeId - node id
* @returns degree of the node
*/
export function getDegree(edges: EdgeData[], nodeId: ID) {
return getRelatedEdgesData(edges, nodeId).length;
}
/**
* Get related edges data of a node
* @param edges - all edges data
* @param nodeId - node id
* @returns related edges data
*/
export function getRelatedEdgesData(edges: EdgeData[], nodeId: ID) {
return edges.filter(edge => edge.source === nodeId || edge.target === nodeId);
}
/**
* Concatenate the labels of the related edges to the node as the node's edge key
* @param edges - all edges data
* @param nodeId - node id
* @returns edge key
*/
export function getCommunityId(edges: EdgeData[], nodeId: ID) {
const relatedEdges = getRelatedEdgesData(edges, nodeId);
const key = relatedEdges
.map(edge => {
const direction = edge.source === nodeId ? '->' : '<-';
const otherEnd = edge.source === nodeId ? edge.target : edge.source;
return `${direction}_${edge.data!.label}_${otherEnd}`;
})
.sort()
.join('+');
return key;
}
/**
* Whether the node is in a community(same communityId) with more than `limit` nodes
* @param data - graph data
* @param nodeId - node id
* @param limit - limit
* @returns boolean
*/
export function isInCommunity(data: GraphData, nodeId: string, limit = 2) {
const groupedNodes = groupBy(data.nodes, node => node.data!.communityId);
const filtered = Object.values(groupedNodes).find(nodes => nodes.map(idOf).includes(nodeId))!;
return filtered.length > limit;
}