2013-12-20 129 views
1

有沒有一種方法可以使用pydot生成一個看起來像「普通樹形圖」的有向樹圖,其中每個相同深度的節點顯示在相同的深度,並且每個邊都處於某個角度(不是直下)?需要控制pydot邊緣長度

當我使用這些默認值:

graph = pydot.Dot(graph_type='digraph', nodesep=.75) 
graph.set_node_defaults(style="filled", fillcolor="grey") 
graph.set_edge_defaults(color="blue", arrowhead="vee", weight="0") 

節點2和1太長之間的邊緣的長度。參見:
enter image description here

我可以使用的邊緣權重校正節點的長度 「1」,如:

graph.set_edge_defaults(顏色= 「藍色」,慈姑= 「V形」,重量= 「1」)

但是現在兩個邊緣的位置2和3,和7和6之間見直下指向: enter image description here

邊指着STR下降事實證明是一個真正的問題。如果左右兄弟姐妹都沒有繪製,那麼不清楚繪製了哪個節點(左或右)。

PS:在我之前關於同一個項目的問題中,我問過如何控制邊緣的角度,所以pydot生成的樹形圖將避免邊緣朝下。 「Guy」很好地回答了這個問題。在使用隱形節點實現Guy的解決方案後,出現了一種新的副作用:某些圖形上某些邊的長度的長度過長。這裏是一個鏈接到前面的問題以供參考:Is there a way to control line angle when producing graphs with pyDot

+0

可能重複的是有辦法控制線使用pyDot生成圖形時的角度(http://stackoverflow.com/questions/20533753/is-there-a-way-to-control-line-angle-when-producing-graphs-with-pydot) – Skyler

+0

不是重複。我之前的問題是關於用一個角度繪製邊緣而不是直線下降。現在新的問題是如何管理邊緣長度。 – LectureMaker

+0

謝謝編輯PK。我對graphviz中的手動工作有這樣一個問題的答案。當它乾淨地工作時,我會在幾天內使用pydot和python發佈我的答案和示例代碼。 – LectureMaker

回答

2

爲了正確控制pydot有向圖的節點位置和邊緣長度,以便在指向相同方向時邊緣彼此平行,沒有邊直接指向下方,所有節點被繪製到適當的級別 - 必須使用不可見的節點。

在關於此主題「如何控制線角度......」的前期SO Q/A會議中,我瞭解到使用不可見節點來填充丟失的葉節點。這適用於一些樹木,但有一些副作用。

現在,我已經學會爲每個節點添加第三個不可見節點,同時具有左右節點。不可見的節點不會添加到樹中,請注意,但只是繪製到圖中。所以樹仍然可以用於搜索,插入,刪除和其他方法。

這裏是一個graphviz的示例演示瞭解決方案:

digraph { 
    nodesep=0.35 
    ordering=out 
    node[style="filled", fillcolor="grey"] 
    edge[color="blue", arrowhead="vee"] 
    { node[shape=point style=invis] m5 m2 m8 m6 m4 } 

    5 -> 2 
    5 -> m5 [weight=100 style=invis] 
    5 -> 8 
    2 -> 1 
    2 -> m2 [weight=100 style=invis] 
    2 -> 4 
    8 -> 6 
    8 -> m8 [weight=100 style=invis] 
    4 -> 3 
    4 -> m4 [weight=100 style=invis] 
    6 -> m6 [weight=100 style=invis] 
    6 -> 7 
} 

這裏是我的更新Python代碼片斷這個過程具有典型的樹類自動化:

vT = visualizeTree(0, fileDir, 'bst_graph','.png',1) # instantiate the visualizeTree Object 
    graph = pydot.Dot(graph_type='digraph', nodesep=.5, pad=.3, size="19.2, 10.1") 
    graph.set_node_defaults(style="filled", fillcolor="grey") 
    graph.set_edge_defaults(color="blue", arrowhead="vee") 
    vT.searchTree(root, sketchTree) 
    vT.updateGraph() 

class visualizeTree(object): 
    # more code and comments located at project home 
    def __init__(self, fileCount, fileDir, fileName, fileExt, vidFrames): 

    def sketchTree(node, stack, find=None, draw=None): 
     if node.getLeftBranch(): 
      draw(str(node), str(node.getLeftBranch())) 
      stack.append(node.getLeftBranch()) 
      if node.getRightBranch(): 
       # insert invisible third node in-between left and right nodes 
       draw(str(node), ":"+str(node), style_type="invisible") 
     elif node.getRightBranch(): 
      # draw any missing left branches as invisible nodes/edges with dummy unique labels 
      draw(str(node), ":"+str(node), style_type="invisible") 
     if node.getRightBranch(): 
      draw(str(node), str(node.getRightBranch())) 
      stack.append(node.getRightBranch())  
     elif node.getLeftBranch(): 
      # draw any missing right branches as invisible nodes/edges with dummy unique labels 
      draw(str(node), ";"+str(node), style_type="invisible") 

    def draw(self, parent_name, child_name, fill_color="grey", style_type='filled'):     
     if style_type=="invisible": 
      # save original edge defaults 
      weight_ = "100" 
      saveEdgeDefaults = graph.get_edge_defaults()[0] 
      graph.set_edge_defaults(style=style_type, color="white", arrowhead="none") 
     else: 
      weight_ = "3" 
     edge = pydot.Edge(parent_name, child_name, style=style_type, weight=weight_) 
     graph.add_edge(edge) 
     if style_type=="invisible": 
      graph.set_edge_defaults(**saveEdgeDefaults)   
     if not self.nodeNames: 
      self.nodeNames[parent_name] = pydot.Node(parent_name, label=parent_name, fillcolor=fill_color, style=style_type) 
      graph.add_node(self.nodeNames[parent_name]) 
     if (parent_name not in self.nodeNames):  
      self.nodeNames[parent_name] = pydot.Node(parent_name, label=parent_name, fillcolor=fill_color, style=style_type) 
      graph.add_node(self.nodeNames[parent_name]) 
     if child_name not in self.nodeNames: 
      self.nodeNames[child_name] = pydot.Node(child_name, label=child_name, fillcolor=fill_color, style=style_type) 
      graph.add_node(self.nodeNames[child_name]) 

完整的源代碼可以在項目的家中找到: http://www.embeddedcomponents.com/blogs/2013/12/visualizing-software-tree-structures/

典型的小圖片,現在畫,因爲我首先想: binary search tree

即使是大型的樹木可以用類似的幾何形狀可以得出: larger binary search tree with ordered search trail

的[