我之前曾尝试过类似的事情,主要想法是尽量避开边缘。
假设边缘是直线,有两种简单且类似的方法可以实现这一点:
基于节点邻域的边缘相对于节点本身所形成的角度。
基于邻域节点的质心。
因此,找到从一个节点到其邻域的边缘形成的角度,并尝试将标签定位在远离大多数边缘的位置;或估计节点邻域的质心并将标签沿相反方向定位。
第一个解决方案可能有点问题,主要是因为atan2函数的操作方式(它本质上决定了边缘角度),但它确实在定位标签方面提供了一些灵活性。
第二种解决方案是最简单的,其工作原理如下:
import networkx as nx
import matplotlib.pyplot as plt
#Build the graph
#Please note, the code here is as per the original post
G=nx.Graph()
G = nx.complete_graph(5)
mapping = {0:'aaaaaaa',1:'bbbbbbb',2:'ccccccc', 3:'dddddddd', 4:'eeeeeeeee'}
G = nx.relabel_nodes(G,mapping)
plt.figure(figsize=(10,10), facecolor="w", frameon=False)
#Get a graph layout
pos = nx.graphviz_layout(G, prog="fdp") #calculate position (x,y) coordinates
#Here is an alternative layout, please see below.
#pos = nx.layout.spring_layout(G)
nx.draw_networkx_nodes(G,pos,node_size=1200,node_shape='^',node_color='0.75')
nx.draw_networkx_edges(G,pos, width=2,edge_color='r')
#Show the original position of the labels using a Green colour.
nx.draw_networkx_labels(G,pos,font_color='g')
#Please note, the code below uses the original idea of re-calculating a dictionary of adjusted label positions per node.
label_ratio = 1.0/8.0
pos_labels = {}
#For each node in the Graph
for aNode in G.nodes():
#Get the node's position from the layout
x,y = pos[aNode]
#Get the node's neighbourhood
N = G[aNode]
#Find the centroid of the neighbourhood. The centroid is the average of the Neighbourhood's node's x and y coordinates respectively.
#Please note: This could be optimised further
cx = sum(map(lambda x:pos[x][0], N)) / len(pos)
cy = sum(map(lambda x:pos[x][1], N)) / len(pos)
#Get the centroid's 'direction' or 'slope'. That is, the direction TOWARDS the centroid FROM aNode.
slopeY = (y-cy)
slopeX = (x-cx)
#Position the label at some distance along this line. Here, the label is positioned at about 1/8th of the distance.
pos_labels[aNode] = (x+slopeX*label_ratio, y+slopeY*label_ratio)
#Finally, redraw the labels at their new position.
nx.draw_networkx_labels(G,pos=pos_labels,fontsize=2)
#Show the figure
plt.show()
这主要适用于主要位于图形外围的节点,但对于位于图形中心的节点具有挑战性,因为质心不会提供避开大部分边的可靠方向。
这是graphviz的fdp布局的输出......
...这是 networkx 的spring layout的输出。
请注意第二个图上绿色和黑色标签的接近程度。本质上,dddddddd 的邻域的质心相对接近节点的实际位置。
对于更复杂的解决方案,您可能需要检查更复杂的算法,例如Wordle 使用的算法,以便在标签与边相交时调整标签的初始位置。
希望这可以帮助。