基于Matplotlib实现动态节点连接/消失的网络图技术咨询
用Matplotlib实现动态节点网络图(2D/3D)
完全可以用Matplotlib结合其animation模块实现你要的效果,以下是2D和3D版本的具体实现代码,核心逻辑包含节点随机生成、移动、距离检测连线/断连、节点自动移除等功能。
2D 动态节点网络图实现
import matplotlib.pyplot as plt import matplotlib.animation as animation import numpy as np # 配置参数 MAX_NODES = 4 NODE_SIZE = 50 CONNECT_THRESHOLD = 0.2 # 节点间距小于该值时连线 MOVE_STEP = 0.02 # 节点每帧移动步长 BOUNDS = (-1, 1) # 节点活动范围 # 初始化画布和坐标轴 fig, ax = plt.subplots(figsize=(6, 6)) ax.set_xlim(*BOUNDS) ax.set_ylim(*BOUNDS) ax.axis('off') # 存储节点数据:[x, y, active] nodes = [] lines = [] def init(): return [] def update(frame): global nodes, lines # 清除旧的绘图元素 for line in lines: line.remove() lines.clear() ax.clear() ax.set_xlim(*BOUNDS) ax.set_ylim(*BOUNDS) ax.axis('off') # 移动现有活跃节点并移除超出边界的节点 new_nodes = [] for x, y, active in nodes: if not active: continue # 随机方向移动 dx = np.random.uniform(-MOVE_STEP, MOVE_STEP) dy = np.random.uniform(-MOVE_STEP, MOVE_STEP) new_x = x + dx new_y = y + dy # 检查是否在边界内,否则标记为不活跃 if BOUNDS[0] <= new_x <= BOUNDS[1] and BOUNDS[0] <= new_y <= BOUNDS[1]: new_nodes.append([new_x, new_y, True]) else: new_nodes.append([new_x, new_y, False]) nodes = [n for n in new_nodes if n[2]] # 随机生成新节点,直到达到最大数量 while len(nodes) < MAX_NODES: x = np.random.uniform(*BOUNDS) y = np.random.uniform(*BOUNDS) nodes.append([x, y, True]) # 绘制节点 x_coords = [n[0] for n in nodes] y_coords = [n[1] for n in nodes] ax.scatter(x_coords, y_coords, s=NODE_SIZE, c='darkblue', edgecolor='white') # 检查节点距离并绘制连线 for i in range(len(nodes)): for j in range(i+1, len(nodes)): x1, y1 = nodes[i][0], nodes[i][1] x2, y2 = nodes[j][0], nodes[j][1] dist = np.sqrt((x1-x2)**2 + (y1-y2)**2) if dist < CONNECT_THRESHOLD: line, = ax.plot([x1, x2], [y1, y2], color='gray', linewidth=1.5) lines.append(line) return [] # 启动动画 ani = animation.FuncAnimation(fig, update, init_func=init, interval=50, blit=True) plt.show()
核心逻辑说明
- 节点管理:用列表存储节点的坐标和活跃状态,超出边界的节点会被移除
- 连线规则:计算每对节点的欧氏距离,小于阈值时绘制连线
- 动态更新:每帧清除旧的绘图元素,重新绘制当前活跃节点和有效连线,同时补充新节点
3D 动态节点网络图实现
只需将坐标轴改为3D,调整坐标计算逻辑即可:
import matplotlib.pyplot as plt import matplotlib.animation as animation import numpy as np # 配置参数 MAX_NODES = 4 NODE_SIZE = 100 CONNECT_THRESHOLD = 0.3 MOVE_STEP = 0.02 BOUNDS = (-1, 1) # 初始化3D画布 fig = plt.figure(figsize=(8, 8)) ax = fig.add_subplot(projection='3d') ax.set_xlim(*BOUNDS) ax.set_ylim(*BOUNDS) ax.set_zlim(*BOUNDS) ax.axis('off') nodes = [] lines = [] def init(): return [] def update(frame): global nodes, lines # 清除旧元素 for line in lines: line.remove() lines.clear() ax.clear() ax.set_xlim(*BOUNDS) ax.set_ylim(*BOUNDS) ax.set_zlim(*BOUNDS) ax.axis('off') # 移动节点并移除超出边界的节点 new_nodes = [] for x, y, z, active in nodes: if not active: continue dx = np.random.uniform(-MOVE_STEP, MOVE_STEP) dy = np.random.uniform(-MOVE_STEP, MOVE_STEP) dz = np.random.uniform(-MOVE_STEP, MOVE_STEP) new_x = x + dx new_y = y + dy new_z = z + dz if all(BOUNDS[0] <= coord <= BOUNDS[1] for coord in [new_x, new_y, new_z]): new_nodes.append([new_x, new_y, new_z, True]) else: new_nodes.append([new_x, new_y, new_z, False]) nodes = [n for n in new_nodes if n[3]] # 补充新节点 while len(nodes) < MAX_NODES: x = np.random.uniform(*BOUNDS) y = np.random.uniform(*BOUNDS) z = np.random.uniform(*BOUNDS) nodes.append([x, y, z, True]) # 绘制节点 x_coords = [n[0] for n in nodes] y_coords = [n[1] for n in nodes] z_coords = [n[2] for n in nodes] ax.scatter(x_coords, y_coords, z_coords, s=NODE_SIZE, c='darkblue', edgecolor='white') # 绘制连线 for i in range(len(nodes)): for j in range(i+1, len(nodes)): x1, y1, z1 = nodes[i][0], nodes[i][1], nodes[i][2] x2, y2, z2 = nodes[j][0], nodes[j][1], nodes[j][2] dist = np.sqrt((x1-x2)**2 + (y1-y2)**2 + (z1-z2)**2) if dist < CONNECT_THRESHOLD: line, = ax.plot([x1, x2], [y1, y2], [z1, z2], color='gray', linewidth=1.5) lines.append(line) return [] ani = animation.FuncAnimation(fig, update, init_func=init, interval=50, blit=True) plt.show()
3D版本调整点
- 使用
projection='3d'创建3D坐标轴 - 节点增加z坐标维度,移动和边界检测都扩展到三维
- 连线计算改用三维欧氏距离
你可以根据需求调整参数(如节点大小、移动步长、连线阈值等)来匹配参考图的视觉效果。
内容的提问来源于stack exchange,提问作者KVANKER KVANKERI
相关产品推荐
相关产品推荐

