绘图与用Python渲染多路树 [英] Drawing & Rendering Multiway Tree in Python

查看:126
本文介绍了绘图与用Python渲染多路树的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有人知道我该如何以美学上合理的方式绘制多路树? 信息:

  • 或多或少100个项目
  • 每个级别的项目数量大致相同
  • 10个级别
  • 每个节点的子级介于0(叶)和6个子之间
  • 每个节点都指定自己的级别,而不管其根源为何.

我目前正在使用PIL,将每条线"划分为img.size()[0]/节点数,并用draw.line画线来表示边缘,但是它被完全弄乱了

希望您能帮助我=],我将发布任何需要的信息.

解决方案

因此,渲染图是 graphviz ,也恰好有几个提供python绑定的库.我认为,这些绑定库中最好的是 pygraphviz . Graphviz可能是最好的解决方案,也可能是最简单的解决方案.

您在问题中描述的特定布局是一种分层的分层方案,它是由graphviz的 dot 布局引擎毫不费力地执行的. Dot 进行渲染以确保图形以自然树结构布局-即,父节点位于其子节点上方;在可能的情况下,等等级的节点(从根开始的级别)与y轴相等,并且在可能的情况下保留自然的对称性.

(注:令人困惑的是, dot 指的是构成 graphviz 的几种布局引擎之一,但是 dot 也是名称和文件扩展名所有graphviz文档的文件格式,无论其呈现方式如何).

如下面的代码所示,使用pygraphviz可以很容易地选择 dot 作为图形的布局引擎,尽管实际上这并不是默认设置( neato 是).

这是我制作的一个快速图形,然后使用 dot 进行渲染-通过 pygraphviz 使用 graphviz 创建和渲染.

请注意,该图具有完美的布局-相同程度的节点沿垂直轴位于同一水平上,子级显示在父级下方,并且在可能的情况下保留自然的对称性"(例如,父级节点位于并在其两个子节点之上,如您所见,我的代码都没有手动控制布局-graphviz(即 dot )会自动对其进行处理.

import pygraphviz as PG

A = PG.AGraph(directed=True, strict=True)

A.add_edge("7th Edition", "32V")
A.add_edge("7th Edition", "Xenix")
# etc., etc.

# save the graph in dot format
A.write('ademo.dot')

# pygraphviz renders graphs in neato by default, 
# so you need to specify dot as the layout engine
A.layout(prog='dot')


# opening the dot file in a text editor shows the graph's syntax:
digraph unix {
  size="7,5";
  node [color=goldenrod2, style=filled];
  "7th Edition" -> "32V";
  "7th Edition" -> "V7M";
  "7th Edition" -> "Xenix";
  "7th Edition" -> "UniPlus+";
  "V7M" -> "Ultrix-11";
  "8th Edition" -> "9th Edition";
  "1 BSD" -> "2 BSD";
  "2 BSD" -> "2.8 BSD";
  "2.8 BSD" -> "Ultrix-11";
  "2.8 BSD" -> "2.9 BSD";
  "32V" -> "3 BSD";
  "3 BSD" -> "4 BSD";
  "4 BSD" -> "4.1 BSD";
  "4.1 BSD" -> "4.2 BSD";
  "4.1 BSD" -> "2.8 BSD";
  "4.1 BSD" -> "8th Edition";
  "4.2 BSD" -> "4.3 BSD";
  "4.2 BSD" -> "Ultrix-32";
}

Does somebody know how do I plot a multiway-tree in a aesthetically plausible way? info:

  • more or less 100 items
  • each level have approximately the same number of items
  • 10 levels
  • each node have between 0(leaf) and 6 childs
  • each node specify it's own level, no matter his roots.

I'm currently using PIL, dividing each "line" in img.size()[0]/number of nodes, and drawing lines with draw.line to represent edges, but it is completely messed up

I hope you can help me =], any information needed I'll post.

解决方案

So, rendering graphs is the particular genius of graphviz, which also happens to have several libraries that provide python bindings. In my opinion, the best of these bindings libraries is pygraphviz. Graphviz is probably the best solution and also likely the simplest.

The particular layout you describe in your Question, a hierarchical, layered scheme, is performed effortlessly by graphviz' dot layout engine. Dot performs the rendering to ensure that the graph is laid out in a natural tree configuration--i.e., parent nodes are positioned above their children; nodes of equal rank (levels from the root) are equi-positioned w/r/t the y-axis when possible, and natural symmetry is preserved when possible.

(Note: confusingly, dot refers to one of several layout engines that comprise graphviz, but dot is also the name and file extension of the file format for all graphviz documents regardless of how they are rendered).

As you can see in my code that follows, using pygraphviz, it's simple to select dot as layout engine for your graph, though it's not actually the default (neato is).

Here's a quick graph i made and then rendered using dot--created and rendered using graphviz via pygraphviz.

Notice that the graph has perfect layout--nodes of the same degree are on the same level along a vertical axis, children are rendered below parents and natural 'symmetry' is preserved when possible (e.g., a parent node is positioned between and above its two child nodes. And as you can see, none of my code manually controls the layout--graphviz, i.e., dot, handles it automatically.

import pygraphviz as PG

A = PG.AGraph(directed=True, strict=True)

A.add_edge("7th Edition", "32V")
A.add_edge("7th Edition", "Xenix")
# etc., etc.

# save the graph in dot format
A.write('ademo.dot')

# pygraphviz renders graphs in neato by default, 
# so you need to specify dot as the layout engine
A.layout(prog='dot')


# opening the dot file in a text editor shows the graph's syntax:
digraph unix {
  size="7,5";
  node [color=goldenrod2, style=filled];
  "7th Edition" -> "32V";
  "7th Edition" -> "V7M";
  "7th Edition" -> "Xenix";
  "7th Edition" -> "UniPlus+";
  "V7M" -> "Ultrix-11";
  "8th Edition" -> "9th Edition";
  "1 BSD" -> "2 BSD";
  "2 BSD" -> "2.8 BSD";
  "2.8 BSD" -> "Ultrix-11";
  "2.8 BSD" -> "2.9 BSD";
  "32V" -> "3 BSD";
  "3 BSD" -> "4 BSD";
  "4 BSD" -> "4.1 BSD";
  "4.1 BSD" -> "4.2 BSD";
  "4.1 BSD" -> "2.8 BSD";
  "4.1 BSD" -> "8th Edition";
  "4.2 BSD" -> "4.3 BSD";
  "4.2 BSD" -> "Ultrix-32";
}

这篇关于绘图与用Python渲染多路树的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆