如何制作具有多个根树的圆形树

Posted

技术标签:

【中文标题】如何制作具有多个根树的圆形树【英文标题】:How do I make a circular tree with multiple root trees 【发布时间】:2020-07-16 20:14:02 【问题描述】:

使用从这个question 转换为python Radial Positions algorithm 的C,我已经成功地创建了一个基于根节点的径向图,一直到每个节点的最后一个子节点。现在我有一个新问题,我有多个根节点,需要它们以找到的第一个根为中心,或者至少是一个中心点。

我找到的最接近的例子是这张图:

到目前为止,我所能想到的只是对于找到的每个根节点,将其乘以它的索引,然后将 x 位置与 y 半径相加。到目前为止,它的效果并不好,因为我的子节点不遵循它。这几天我一直被这个问题难住了。

def RadialPositions(node, id):

    children_in_node = len(timelinedatta.neighbors(id, mode="out"))

    def rotate_node(x, y, nangle):
        nx = x * math.cos(nangle) - y * math.sin(nangle)
        ny = x * math.sin(nangle) + y * math.cos(nangle)
        return nx, ny

    def get_depth(id):
        count = 0
        for v in timelinedatta.bfsiter(id, mode="in", advanced=True):
            count = count + 1
        return count - 1

    if len(timelinedatta.neighbors(id, mode="out")) > 0 and len(timelinedatta.neighbors(id, mode="in")) == 0:
        node["positions"] = (0, 0)

    node["depth"] = get_depth(id)
    
    node_children_list = []

    for child in timelinedatta.neighbors(id, mode="out"):
        node_children_list.append((child, timelinedatta.vs[child]))

    for idx, (child_node_id, child_node) in enumerate(node_children_list, start=0):


        centerAdjust = 0

        if timelinedatta.neighbors(id, mode="in"):
            centerAdjust = (-node["angleRange"] + node["angleRange"] / children_in_node) / 2

        child_node["depth"] = get_depth(child_node_id)
        child_depth = child_node["depth"]



        child_node["nodeAngle"] = node["nodeAngle"] + node["angleRange"] / children_in_node * idx + centerAdjust
        child_node["angleRange"] = node["angleRange"] / children_in_node

        nx = rotate_node(40 * child_depth, 0, child_node["nodeAngle"])[0]
        ny = rotate_node(40 * child_depth, 0, child_node["nodeAngle"])[1]
        
        child_node["positions"] = [2 * nx, 2 * ny]


        RadialPositions(child_node, child_node_id)

我的图表 here 在 pastebin 上也有一个示例

【问题讨论】:

您有任何想要表示的图表示例吗? @OneLyner 是的,我已经用有向图更新了我的答案。 pastebin.com/51NH7phr 不确定您的具体问题,但不是重新发明,而是检查graphviz.readthedocs.io/en/stable 吗?这顺利地使用了实际的en.wikipedia.org/wiki/Graphviz,在 C 中实现。 @thoku 我很想使用 Graphviz,但对于我的实现,我需要在不同的应用程序中显示所有图形信息。虽然我尝试过查看 Graphviz 的算法,但我对 C 不太了解 【参考方案1】:

您可以将graphviz(由@thoku 建议)与neato 布局引擎(man neato)一起使用:

neato 使用 spring 模型绘制无向图并减少相关能量(请参阅 Kamada and Kawai, Information Processing Letters 31:1, April 1989)。

例如,例子

from graphviz import Digraph

tree = Digraph(engine='neato')

tree.node('root1',"R1")
tree.node('root2',"R2")
tree.node('root3',"R3")
tree.node('root4',"R4")
tree.edge('root1','root2')
tree.edge('root1','root3')
tree.edge('root3','root4')

tree.node('child11',"C11")
tree.node('child12',"C12")
tree.node('child13',"C13")
tree.edge('root1','child11')
tree.edge('root1','child12')
tree.edge('root1','child13')

tree.node('child21',"C21")
tree.node('child22',"C22")
tree.edge('root2','child21')
tree.edge('root2','child22')

tree.node('child31',"C31")
tree.node('child32',"C32")
tree.edge('root3','child31')
tree.edge('root3','child32')

tree.node('child41',"C41")
tree.node('child42',"C42")
tree.node('child43',"C43")
tree.edge('root4','child41')
tree.edge('root4','child42')
tree.edge('root4','child43')

tree.render("tree")

生成以下输出:

【讨论】:

我回复了 thoku,但我使用的是有向图,需要使用 python 手动呈现该图以用于不同的应用程序。 @Khailz 我已经更新了有向图的示例。 如果您想要更好的东西,也可以使用 snoopviz Graphviz 似乎也有一个位置 api,所以这很适合我的需要。将根节点相互分配会产生需要的效果。谢谢

以上是关于如何制作具有多个根树的圆形树的主要内容,如果未能解决你的问题,请参考以下文章

bzoj4337树的同构

4337. [BJOI2015]树的同构树哈希

树hs[BJOI2015]树的同构

P5043 模板树同构([BJOI2015]树的同构) |树哈希

BZOJ3244UOJ#122NOI2013]树的计数

[bzoj3244] [洛谷P1232] [Noi2013] 树的计数