【发布时间】:2020-07-14 05:36:09
【问题描述】:
我使用以下代码生成了一个 3D 图形网络,并使用 Mayavi 进行可视化。
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import networkx as nx
from mayavi import mlab
pos = [[0.1, 2, 0.3], [40, 0.5, -10],
[0.1, -40, 0.3], [-49, 0.1, 2],
[10.3, 0.3, 0.4], [-109, 0.3, 0.4]]
pos = pd.DataFrame(pos, columns=['x', 'y', 'z'])
ed_ls = [(x, y) for x, y in zip(range(0, 5), range(1, 6))]
G = nx.Graph()
G.add_edges_from(ed_ls)
nx.draw(G)
plt.show()
# plot 3D in mayavi
edge_size = 0.2
edge_color = (0.8, 0.8, 0.8)
bgcolor = (0, 0, 0)
mlab.figure(1, bgcolor=bgcolor)
mlab.clf()
for i, e in enumerate(G.edges()):
# ----------------------------------------------------------------------------
# the x,y, and z co-ordinates are here
pts = mlab.points3d(pos['x'], pos['y'], pos['z'],
scale_mode='none',
scale_factor=1)
# ----------------------------------------------------------------------------
pts.mlab_source.dataset.lines = np.array(G.edges())
tube = mlab.pipeline.tube(pts, tube_radius=edge_size)
mlab.pipeline.surface(tube, color=edge_color)
mlab.show()
我想就如何以 VTK 格式保存这个 3D 图形/如何 将 Networkx 图形对象转换为 VTK 文件,以便在 Paraview 中进行可视化。
编辑: 我已经尝试为输入 Networkx 图调整可用的代码 here 以上分享。但是,我无法获得输出。我只是得到一个空窗口,并且 vtkpolyData 没有绘制在窗口中。
"""
This code converts netwrokx graph to vtk polyData
ref: https://networkx.github.io/documentation/networkx-0.37/networkx.drawing.nx_vtk-pysrc.html
"""
import vtk
import pandas as pd
import networkx as nx
import matplotlib.pyplot as plt
from vtk.util.colors import banana, plum
def draw_nxvtk(G, node_pos):
"""
Draw networkx graph in 3d with nodes at node_pos.
See layout.py for functions that compute node positions.
node_pos is a dictionary keyed by vertex with a three-tuple
of x-y positions as the value.
The node color is plum.
The edge color is banana.
All the nodes are the same size.
"""
# set node positions
np={}
for n in G.nodes():
try:
np[n]=node_pos[n]
except nx.NetworkXError:
print("node %s doesn't have position"%n)
nodePoints = vtk.vtkPoints()
i=0
for (x,y,z) in np.values():
nodePoints.InsertPoint(i, x, y, z)
i=i+1
# Create a polydata to be glyphed.
inputData = vtk.vtkPolyData()
inputData.SetPoints(nodePoints)
# Use sphere as glyph source.
balls = vtk.vtkSphereSource()
balls.SetRadius(.05)
balls.SetPhiResolution(20)
balls.SetThetaResolution(20)
glyphPoints = vtk.vtkGlyph3D()
glyphPoints.SetInputData(inputData)
glyphPoints.SetSourceData(balls.GetOutput())
glyphMapper = vtk.vtkPolyDataMapper()
glyphMapper.SetInputData(glyphPoints.GetOutput())
glyph = vtk.vtkActor()
glyph.SetMapper(glyphMapper)
glyph.GetProperty().SetDiffuseColor(plum)
glyph.GetProperty().SetSpecular(.3)
glyph.GetProperty().SetSpecularPower(30)
# Generate the polyline for the spline.
points = vtk.vtkPoints()
edgeData = vtk.vtkPolyData()
# Edges
lines = vtk.vtkCellArray()
i = 0
for e in G.edges():
# The edge e can be a 2-tuple (Graph) or a 3-tuple (Xgraph)
u = e[0]
v = e[1]
if v in node_pos and u in node_pos:
lines.InsertNextCell(2)
for n in (u, v):
(x, y, z) = node_pos[n]
points.InsertPoint(i, x, y, z)
lines.InsertCellPoint(i)
i = i+1
edgeData.SetPoints(points)
edgeData.SetLines(lines)
# Add thickness to the resulting line.
Tubes = vtk.vtkTubeFilter()
Tubes.SetNumberOfSides(16)
Tubes.SetInputData(edgeData)
Tubes.SetRadius(.01)
#
profileMapper = vtk.vtkPolyDataMapper()
profileMapper.SetInputData(Tubes.GetOutput())
#
profile = vtk.vtkActor()
profile.SetMapper(profileMapper)
profile.GetProperty().SetDiffuseColor(banana)
profile.GetProperty().SetSpecular(.3)
profile.GetProperty().SetSpecularPower(30)
# Now create the RenderWindow, Renderer and Interactor
ren = vtk.vtkRenderer()
renWin = vtk.vtkRenderWindow()
renWin.AddRenderer(ren)
iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(renWin)
# Add the actors
ren.AddActor(glyph)
ren.AddActor(profile)
renWin.SetSize(640, 640)
iren.Initialize()
renWin.Render()
iren.Start()
if __name__ == "__main__":
pos = [[0.1, 2, 0.3], [40, 0.5, -10],
[0.1, -40, 0.3], [-49, 0.1, 2],
[10.3, 0.3, 0.4], [-109, 0.3, 0.4]]
pos = pd.DataFrame(pos, columns=['x', 'y', 'z'])
pos_d = pos.T.to_dict(orient='list')
ed_ls = [(x, y) for x, y in zip(range(0, 5), range(1, 6))]
G = nx.Graph()
G.add_edges_from(ed_ls)
# nx.draw(G, with_labels=True, pos=nx.spring_layout(G))
# plt.show()
draw_nxvtk(G=G, node_pos=pos_d)
关于如何在运行上述代码时查看显示的 polyData 输出以及如何保存 vtkPolyData 以在 Paraview 中导入的建议将非常有帮助。
【问题讨论】:
-
这个问题和答案对你有帮助吗? stackoverflow.com/questions/54131133/…
-
@Sparky05 谢谢,我试试看
-
@Sparky05 你能看看我的编辑吗?
标签: networkx vtk mayavi paraview graph-visualization