使用 Dot/GraphViz 进行家谱布局
我正在尝试用 Dot 和 GraphViz 绘制家谱。
这就是我目前所拥有的:
# just graph set-up
digraph simpsons {
ratio = "auto"
mincross = 2.0
# draw some nodes
"Abraham" [shape=box, regular=1, color="blue"] ;
"Mona" [shape=box, regular=1, color="pink"] ;
"Clancy" [shape=box, regular=1, color="blue"] ;
"Jackeline" [shape=box, regular=1, color="pink"] ;
"Herb" [shape=box, regular=1, color="blue"] ;
"Homer" [shape=box, regular=1, color="blue"] ;
"Marge" [shape=box, regular=1, color="pink"] ;
"Patty" [shape=box, regular=1, color="pink"] ;
"Selma" [shape=box, regular=1, color="pink"] ;
"Bart" [shape=box, regular=1, color="blue"] ;
"Lisa" [shape=box, regular=1, color="pink"] ;
"Maggie" [shape=box, regular=1, color="pink"] ;
"Ling" [shape=box, regular=1, color="blue"] ;
# creating tiny nodes w/ no label, no color
"ParentsHomer" [shape=diamond,style=filled,label="",height=.1,width=.1] ;
"ParentsMarge" [shape=diamond,style=filled,label="",height=.1,width=.1] ;
"ParentsBart" [shape=diamond,style=filled,label="",height=.1,width=.1] ;
# draw the edges
"Abraham" -> "ParentsHomer" [dir=none, weight=1] ;
"Mona" -> "ParentsHomer" [dir=none, weight=1] ;
"ParentsHomer" -> "Homer" [dir=none, weight=2] ;
"ParentsHomer" -> "Herb" [dir=none, weight=2] ;
"Clancy" -> "ParentsMarge" [dir=none, weight=1] ;
"Jackeline" -> "ParentsMarge" [dir=none, weight=1] ;
"ParentsMarge" -> "Marge" [dir=none, weight=2] ;
"ParentsMarge" -> "Patty" [dir=none, weight=2] ;
"ParentsMarge" -> "Selma" [dir=none, weight=2] ;
"Homer" -> "ParentsBart" [dir=none, weight=1] ;
"Marge" -> "ParentsBart" [dir=none, weight=1] ;
"ParentsBart" -> "Bart" [dir=none, weight=2] ;
"ParentsBart" -> "Lisa" [dir=none, weight=2] ;
"ParentsBart" -> "Maggie" [dir=none, weight=2] ;
"Selma" -> "Ling" [dir=none, weight=2] ;
}
如果我通过 dot (dot simpsons.dot -Tsvg > simpsons.svg
) 运行它, 我得到以下布局:
但是,我希望边缘更像“家谱”:两个已婚人士之间的 T 形连接处,T 形的垂直线再次在倒置的 T 形连接处分支,并为每个孩子进行小细分,就像这个在 KolourPaint 中完成的模型:
我必须使用什么点语法来实现此目的?
I am trying to draw a family tree with Dot and GraphViz.
This is what I currently have:
# just graph set-up
digraph simpsons {
ratio = "auto"
mincross = 2.0
# draw some nodes
"Abraham" [shape=box, regular=1, color="blue"] ;
"Mona" [shape=box, regular=1, color="pink"] ;
"Clancy" [shape=box, regular=1, color="blue"] ;
"Jackeline" [shape=box, regular=1, color="pink"] ;
"Herb" [shape=box, regular=1, color="blue"] ;
"Homer" [shape=box, regular=1, color="blue"] ;
"Marge" [shape=box, regular=1, color="pink"] ;
"Patty" [shape=box, regular=1, color="pink"] ;
"Selma" [shape=box, regular=1, color="pink"] ;
"Bart" [shape=box, regular=1, color="blue"] ;
"Lisa" [shape=box, regular=1, color="pink"] ;
"Maggie" [shape=box, regular=1, color="pink"] ;
"Ling" [shape=box, regular=1, color="blue"] ;
# creating tiny nodes w/ no label, no color
"ParentsHomer" [shape=diamond,style=filled,label="",height=.1,width=.1] ;
"ParentsMarge" [shape=diamond,style=filled,label="",height=.1,width=.1] ;
"ParentsBart" [shape=diamond,style=filled,label="",height=.1,width=.1] ;
# draw the edges
"Abraham" -> "ParentsHomer" [dir=none, weight=1] ;
"Mona" -> "ParentsHomer" [dir=none, weight=1] ;
"ParentsHomer" -> "Homer" [dir=none, weight=2] ;
"ParentsHomer" -> "Herb" [dir=none, weight=2] ;
"Clancy" -> "ParentsMarge" [dir=none, weight=1] ;
"Jackeline" -> "ParentsMarge" [dir=none, weight=1] ;
"ParentsMarge" -> "Marge" [dir=none, weight=2] ;
"ParentsMarge" -> "Patty" [dir=none, weight=2] ;
"ParentsMarge" -> "Selma" [dir=none, weight=2] ;
"Homer" -> "ParentsBart" [dir=none, weight=1] ;
"Marge" -> "ParentsBart" [dir=none, weight=1] ;
"ParentsBart" -> "Bart" [dir=none, weight=2] ;
"ParentsBart" -> "Lisa" [dir=none, weight=2] ;
"ParentsBart" -> "Maggie" [dir=none, weight=2] ;
"Selma" -> "Ling" [dir=none, weight=2] ;
}
If I run this through dot (dot simpsons.dot -Tsvg > simpsons.svg
),
I get the following layout:
However, I'd like the edges to be more "family tree"-like: a T-junction between two married persons with the vertical line of the T again branching in an upside-down T-junction with small subdivisions for each of the children, like this mock-up, done in KolourPaint:
What is the dot syntax that I have to use to achieve this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
尝试以下操作:
生成:
Try the following:
Produces:
我不认为你可以采用任意的家谱并自动生成一个点文件,它在 GraphViz 中总是看起来不错。
但我认为你可以总是让它看起来不错,如果你:
OP 所希望的
遵守以下规则的树的子集:
这最终将同时显示不超过 3 代,其中 S 位于中间代。
在下图中,S=Homer(对 Brian Blank 的版本稍作修改):
这会生成 GraphViz 的以下树(带有我用 Power Point 添加的注释):
I don’t think you can take an arbitrary family tree and auto-generate a dot file where it always looks good in GraphViz.
But I think you can always make it look good if you:
desired by the OP
subset of the tree that obeys the following rules:
This will end up showing no more than 3 generations at once, with S in the middle generation.
In the picture below S=Homer (slightly modified from Brian Blank's version):
This yields the following tree by GraphViz (with annotations I added with Power Point):
Gramps (www.gramps-project.org) 生成带有或不带有婚姻节点的家谱点文件。
还有一种方法可以在 Gramps 界面本身中看到这一点。 http://gramps-project.org/wiki/index.php?title=Graph_View
所以我想说,看看 Gramps 创建的家谱的输出
Gramps (www.gramps-project.org) generates dot files for family trees, with or without marriage nodes.
There is also a way to see this in the Gramps interface itself. http://gramps-project.org/wiki/index.php?title=Graph_View
So I would say, look at the output of your family tree as created by Gramps
尽管您无法控制节点放置,但我发现您可以通过以不同的顺序对节点进行排序来帮助节点放置。我重新排序了一些节点,如下所示,得到了一个没有产生交叉的图表。
以下代码:
现在生成:
我不完全理解它为什么起作用,但这是想法过程到我所做的改变。
它有效,但我仍然无法设计一种算法来确保树的一致性,没有重叠的边缘。我觉得如果没有这些提示,graphviz 应该做得更好。我不知道使用的算法,但如果他们考虑一个目标函数来最小化或消除重叠边缘,应该可以设计出更好的算法。
Although you can't control node placement, I found you can help node placement by ordering the nodes in a different order. I re-ordered some of the nodes as shown below and got a graph that produced no cross-overs.
The following code:
now produces this:
I don't fully understand why it's working, but here is the thought process into the changes that I made.
It worked, but I still can't devise an algorithm that would ensure consistent trees with no overlapping edges. I feel that graphviz should do a better job without these hints. I don't know the algorithm used, but if they consider an objective function to minimize or eliminate overlapping edges, it should be possible to devise a better algorithm.
在 graphviz 中做到这一点相当简单;您需要几种语法模式:
(i) 表示线与线连接的语法(上图中的“T”形连接); (ii) 强制分层结构的语法(即,同一代的节点位于垂直轴上的同一平面上)。它更容易显示:
上面的代码将生成下面的图形(我省略了用于为节点着色的代码)。我在左侧留下了可见的“指南”(g1->g2....)只是为了向您展示我如何强制执行同等等级节点之间的位置,您可能希望使其在您自己的图中不可见。最后,标签以“ph”开头的节点是“T 形路口”的占位符节点。
To do this in graphviz is fairly straightforward; there are a couple of syntax patterns you need:
(i) syntax to represent the line-to-line connection (the "T"-junction in your plots above); (ii) syntax to enforce the hierarchical structure (i.e., nodes of same generation on the same plane on the vertical axis). It's easier to show:
The code above will produce the graph below (i omitted the code i used to color the nodes). I left vislble the "guide" on the left (g1->g2....) just to show you how i enforced the positions among nodes of equal rank, you'll probably want to make it invisible in your own plots. Finally, the nodes with the labels beginning with 'ph' are the placeholder nodes for the "T-junctions."
我快到了,受到 graphviz 上的旧回复的启发-interest mailinglist 和doug 的回答。
以下代码:
现在生成:
所以,除了 Homer 周围的奇怪边缘之外,看起来不错。如果我能找到一种将亚伯拉罕、莫娜和赫伯移到图片左侧的方法,然后我就会得到一张完美对齐的图片。
关于如何实现这一目标有什么想法吗?
I'm almost there, inspired by an old response on the graphviz-interest mailinglist and doug's answer.
The following code:
now produces this:
So, looks good except for that strange edge around Homer.If I could find a way to move Abraham, Mona and Herb to the left hand side of the picture then I would have a perfectly aligned picture.
Any ideas on how to achieve that?