2012-11-16 40 views
1

我有以下三組整數類似如下:如何在JUNG圖中實施自定義佈局?

set0 = {1} //this will always be a singleton set. 
set1 = {2, 3, 4, 5} 
set2 = {6, 7} 

我有一個具有邊緣它們要麼從SET1到SET2 OR SET2到SET3,從而形成頂點的清晰樹狀層次結構的圖表。

Set0 -- Set1 -- Set2 

要顯示此樹狀圖中我創建了一個DelegateForestTreeLayout

package Test; 

import java.util.HashSet; 
import java.util.Set; 

import javax.swing.JFrame; 
import javax.swing.JPanel; 

import edu.uci.ics.jung.algorithms.layout.Layout; 
import edu.uci.ics.jung.algorithms.layout.TreeLayout; 
import edu.uci.ics.jung.graph.DelegateForest; 
import edu.uci.ics.jung.graph.Forest; 
import edu.uci.ics.jung.graph.Graph; 
import edu.uci.ics.jung.visualization.VisualizationViewer; 
import edu.uci.ics.jung.visualization.decorators.ToStringLabeller; 

class Main{ 
    public static void main(String[] args){ 

    Set<Integer> set0 = new HashSet<Integer>(); 
    Set<Integer> set1 = new HashSet<Integer>(); 
    Set<Integer> set2 = new HashSet<Integer>(); 

    set0.add(1); 

    set1.add(2); 
    set1.add(3); 
    set1.add(4); 
    set1.add(5); 

    set2.add(6); 
    set2.add(7); 

    JFrame frame = new JFrame(); 
    frame.add(createGraphPanel(set0, set1, set2)); 
    frame.pack(); 
    frame.setVisible(true); 


    } 

    private static JPanel createGraphPanel(Set<Integer> setZero, Set<Integer> firstSet, Set<Integer> secondSet) { 
      // create a graph 
      Graph<Integer, String> graph = new DelegateForest<Integer, String>(); 

       Integer vertex1 = setZero.iterator().next(); 
      for (Integer i : firstSet) { 
       graph.addEdge(vertex1+"-"+i, vertex1, i); 
      } 

      Layout<Integer, String> layout = new TreeLayout<Integer, String>((Forest<Integer, String>) graph); 
      VisualizationViewer<Integer, String> vv = new VisualizationViewer<Integer,String>(layout); 

      vv.getRenderContext().setVertexLabelTransformer(
        new ToStringLabeller<Integer>()); 

      return vv; 
     } 
    } 

但是,我得到了(目前只包含設置1和設置2)圖形看起來像這樣 enter image description here

我願做一對夫婦的事情,這個圖:

  1. 而不是從頂部到底部的節點,我希望他們從左到右流動。 (類似於將它旋轉90度)
  2. 目前,佈局算法確保沒有重疊,它以線性方式擴展set2的節點。如果set2很大,它會超出面板的範圍。我不介意重疊,並希望這些節點作爲允許部分重疊的羣集顯示在一起。

我該如何達到這兩個要求?

+0

請發表更多代碼 – durron597

+0

@ durron597添加了創建JPanel對象的函數,您可以將它放在JFrame或您選擇的任何東西上。 – Ankit

+0

比snippets更好會是一個SSCCE - 很確定那麼周圍有人會願意玩它:-) – kleopatra

回答

0

我已經擴展了TreeLayout類並交換了所有的x/y變量。這應該水平顯示樹。但是,您必須添加自己的代碼以防止頂點被排成一行(也許使用邊界框,並在頂過頂點時從頂端開始)。

public class HorizontalOverlappingTreeLayout<V, E> extends TreeLayout<V, E> { 

    public static void main(String[] args) { 
     Set<Integer> set0 = new HashSet<Integer>(); 
     Set<Integer> set1 = new HashSet<Integer>(); 
     Set<Integer> set2 = new HashSet<Integer>(); 
     set0.add(1); 
     set1.add(2); 
     set1.add(3); 
     set1.add(4); 
     set1.add(5); 
     set2.add(6); 
     set2.add(7); 

     JPanel panel = new JPanel(); 
     Graph<Integer, String> graph = new DelegateForest<Integer, String>(); 
     Integer vertex1 = set0.iterator().next(); 
     for (Integer i : set1) { 
      graph.addEdge(vertex1 + "-" + i, vertex1, i); 
     } 

     Layout<Integer, String> layout = new HorizontalOverlappingTreeLayout<Integer, String>(
       (Forest<Integer, String>) graph); 
     VisualizationViewer<Integer, String> vv = new VisualizationViewer<Integer, String>(layout); 
     vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller<Integer>()); 
     panel.add(vv); 

     JFrame frame = new JFrame(); 
     frame.add(panel); 
     frame.pack(); 
     frame.setVisible(true); 
    } 

    public HorizontalOverlappingTreeLayout(Forest<V, E> g) { 
     super(g); 
    } 

    @Override 
    protected void buildTree() { 
     this.m_currentPoint = new Point(0, 20); 
     Collection<V> roots = TreeUtils.getRoots(graph); 
     if (roots.size() > 0 && graph != null) { 
      calculateDimensionY(roots); 
      for (V v : roots) { 
       calculateDimensionY(v); 
       m_currentPoint.y += this.basePositions.get(v)/2 + this.distY; 
       buildTree(v, this.m_currentPoint.y); 
      } 
     } 
     // TODO: removed code here 
    } 

    @Override 
    protected void buildTree(V v, int y) { 
     if (!alreadyDone.contains(v)) { 
      alreadyDone.add(v); 

      // go one level further down 
      this.m_currentPoint.x += this.distX; 
      this.m_currentPoint.y = y; 

      this.setCurrentPositionFor(v); 

      int sizeYofCurrent = basePositions.get(v); 

      int lastY = y - sizeYofCurrent/2; 

      int sizeYofChild; 
      int startYofChild; 

      for (V element : graph.getSuccessors(v)) { 
       sizeYofChild = this.basePositions.get(element); 
       startYofChild = lastY + sizeYofChild/2; 
       buildTree(element, startYofChild); 
       lastY = lastY + sizeYofChild + distY; 
      } 
      this.m_currentPoint.x -= this.distX; 
     } 
    } 

    private int calculateDimensionY(V v) { 
     int size = 0; 
     int childrenNum = graph.getSuccessors(v).size(); 

     if (childrenNum != 0) { 
      for (V element : graph.getSuccessors(v)) { 
       size += calculateDimensionY(element) + distY; 
      } 
     } 
     size = Math.max(0, size - distY); 
     basePositions.put(v, size); 

     return size; 
    } 

    private int calculateDimensionY(Collection<V> roots) { 
     int size = 0; 
     for (V v : roots) { 
      int childrenNum = graph.getSuccessors(v).size(); 

      if (childrenNum != 0) { 
       for (V element : graph.getSuccessors(v)) { 
        size += calculateDimensionY(element) + distY; 
       } 
      } 
      size = Math.max(0, size - distY); 
      basePositions.put(v, size); 
     } 

     return size; 
    } 

} 
2

要回答問題(1):有一個演示(L2RTreeLayoutDemo)來做到這一點。

要回答問題(2):更改佈局中的x和/或y間距;這可以在構造函數中設置。

+1

看起來演示會旋轉查看器(這比編寫自己的佈局類要容易得多): vv.getRenderContext()。getMultiLayerTransformer() .getTransformer(Layer.LAYOUT).rotate(-Math.PI/2,center); – sdasdadas