graph.ts 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. import type { EdgeData, GraphData, ID } from '@antv/g6';
  2. import { idOf } from '@antv/g6';
  3. import { groupBy, pick } from 'lodash';
  4. /**
  5. * Reassign the layout style to the original graph data
  6. * @param model - original graph data
  7. * @param layoutResult - layout result
  8. */
  9. export function reassignLayoutStyle(model: GraphData, layoutResult: GraphData) {
  10. layoutResult.nodes?.forEach(layoutNode => {
  11. const modelNode = model.nodes?.find(node => node.id === layoutNode.id);
  12. if (modelNode?.style) Object.assign(modelNode.style || {}, pick(layoutNode.style, ['x', 'y', 'z']));
  13. });
  14. }
  15. /**
  16. * Calculate node size based on degree
  17. * @param degree - degree of the node
  18. * @param minSize - minimum size of the node
  19. * @param maxSize - maximum size of the node
  20. * @param minDegree - minimum degree
  21. * @param maxDegree - maximum degree
  22. * @returns size of the node
  23. */
  24. export function getSize(degree: number, minSize = 24, maxSize = 60, minDegree = 1, maxDegree = 10): number {
  25. const _degree = Math.max(minDegree, Math.min(maxDegree, degree));
  26. const size = minSize + ((_degree - minDegree) / (maxDegree - minDegree)) * (maxSize - minSize);
  27. return size;
  28. }
  29. /**
  30. * Get node degree, means the number of edges connected to the node
  31. * @param edges - all edges data
  32. * @param nodeId - node id
  33. * @returns degree of the node
  34. */
  35. export function getDegree(edges: EdgeData[], nodeId: ID) {
  36. return getRelatedEdgesData(edges, nodeId).length;
  37. }
  38. /**
  39. * Get related edges data of a node
  40. * @param edges - all edges data
  41. * @param nodeId - node id
  42. * @returns related edges data
  43. */
  44. export function getRelatedEdgesData(edges: EdgeData[], nodeId: ID) {
  45. return edges.filter(edge => edge.source === nodeId || edge.target === nodeId);
  46. }
  47. /**
  48. * Concatenate the labels of the related edges to the node as the node's edge key
  49. * @param edges - all edges data
  50. * @param nodeId - node id
  51. * @returns edge key
  52. */
  53. export function getCommunityId(edges: EdgeData[], nodeId: ID) {
  54. const relatedEdges = getRelatedEdgesData(edges, nodeId);
  55. const key = relatedEdges
  56. .map(edge => {
  57. const direction = edge.source === nodeId ? '->' : '<-';
  58. const otherEnd = edge.source === nodeId ? edge.target : edge.source;
  59. return `${direction}_${edge.data!.label}_${otherEnd}`;
  60. })
  61. .sort()
  62. .join('+');
  63. return key;
  64. }
  65. /**
  66. * Whether the node is in a community(same communityId) with more than `limit` nodes
  67. * @param data - graph data
  68. * @param nodeId - node id
  69. * @param limit - limit
  70. * @returns boolean
  71. */
  72. export function isInCommunity(data: GraphData, nodeId: string, limit = 2) {
  73. const groupedNodes = groupBy(data.nodes, node => node.data!.communityId);
  74. const filtered = Object.values(groupedNodes).find(nodes => nodes.map(idOf).includes(nodeId))!;
  75. return filtered.length > limit;
  76. }