Как раскрасить края трехмерного графика в Mayavi? - PullRequest
1 голос
/ 27 апреля 2020

У меня есть 3D-график, созданный с помощью Mayavi, и края должны быть закрашены скалярным значением.

Следующий код создает график, но я не уверен, как закрасить края

import networkx as nx
import matplotlib.pyplot as plt
import numpy as np
from mayavi import mlab

def main(edge_color=(0.8, 0.8, 0.8), edge_size=0.02):

    t = [1, 2, 4, 4, 5, 3, 5]
    h = [2, 3, 6, 5, 6, 4, 1]


    ed_ls = [(x, y) for x, y in zip(t, h)]
    G = nx.OrderedGraph()
    G.add_edges_from(ed_ls)
    nx.draw(G)
    plt.show()

    graph_pos = nx.spring_layout(G, dim=3)

    # numpy array of x,y,z positions in sorted node order
    xyz = np.array([graph_pos[v] for v in sorted(G)])
    mlab.figure(1)
    mlab.clf()
    pts = mlab.points3d(xyz[:, 0], xyz[:, 1], xyz[:, 2])
    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()  # interactive window

main()

Скалярные значения, которые будут использоваться для окрашивания краев

scalar = [0.1, 0.7, 0.3, 0.5, 0.9, 0.8, 0.2]

Любые предложения о том, как это сделать, будут действительно полезны.

Я также вижу другую проблему в 3D-графике, которая заключается в том, что был создан. Один из ребер не связан с узлом.

enter image description here

РЕДАКТИРОВАТЬ: Насколько я понимаю, mlab.pipeline.surface (tube, color = edge_color )
используется для окраски кромки / трубки.

Обновленный код:

def main(edge_color=(0.8, 0.2, 0.8), edge_size=0.02, graph_colormap='winter'):
    t = [1, 2, 4, 4, 5, 3, 5]
    h = [2, 3, 6, 5, 6, 4, 1]

    ed_ls = [(x, y) for x, y in zip(t, h)]
    G = nx.OrderedGraph()
    G.add_edges_from(ed_ls)
    nx.draw(G)
    plt.show()
    scalars = np.array(G.nodes())+5
    pprint(scalars)
    e_color = [(0.8, 0.2, 0.8), (0.8, 0.2, 0.8), (0.8, 0.2, 0.8),
               (0.8, 0.2, 0.8), (0.8, 0.2, 0.8), (0.8, 0.2, 0.8),
               (0.8, 0.2, 0.8)]
    graph_pos = nx.spring_layout(G, dim=3)

    # numpy array of x,y,z positions in sorted node order
    xyz = np.array([graph_pos[v] for v in sorted(G)])
    mlab.figure(1)
    mlab.clf()
    pts = mlab.points3d(xyz[:, 0], xyz[:, 1], xyz[:, 2],
                        scalars,
                        colormap=graph_colormap
                        )
    pts.mlab_source.dataset.lines = np.array(G.edges())
    tube = mlab.pipeline.tube(pts, tube_radius=edge_size)
    #mlab.pipeline.surface(tube, color=e_color)  # doesn't work
    mlab.pipeline.surface(tube, color=edge_color)  # doesn't work

    mlab.show()  # interactive window

Но проблема в том, что я не могу назначить другой цвет для другой кромки / трубки

1 Ответ

0 голосов
/ 29 апреля 2020

Возможное решение, совсем не автоматизированное, но достаточное для подтверждения концепции.

import networkx as nx
import numpy as np
from mayavi import mlab

t = [1, 2, 4, 4, 5, 3, 5]
h = [2, 3, 6, 5, 6, 4, 1]
ed_ls = [(x, y) for x, y in zip(t, h)]
G = nx.OrderedGraph()
G.add_edges_from(ed_ls)
graph_pos = nx.spring_layout(G, dim=3)
xyz = np.array([graph_pos[v] for v in G])
print(xyz.shape)
mlab.points3d(xyz[:, 0], xyz[:, 1], xyz[:, 2],
              np.linspace(1, 2, xyz.shape[0]),
              colormap='winter', resolution=100, scale_factor=0.3)
smallTri = np.tile(xyz[-3:, :], (2, 1))[:4, :]
remEdges = np.vstack((xyz[-1, :], xyz[:-2, :]))
allEdges = np.vstack((smallTri, remEdges))
for i in range(allEdges.shape[0] - 1):
    mlab.plot3d(allEdges[i:i + 2, 0], allEdges[i:i + 2, 1],
                allEdges[i:i + 2, 2], color=(0.2, 1 - 0.1 * i, 0.8))
mlab.show()

enter image description here

...