2014-06-20 2 views
3

다음과 같은 jung2 시각화를 만들었습니다. 내 코드는 텍스트를 나무로 시각화합니다. 기본적으로 나는 한 번에 두 개의 입력, 하나를 사용하고 있습니다 :java.lang.IllegalArgumentException : 트리에 하위 항목이 없습니다.

 /* 
     * INPUT 1 
     */ 
     String text = "=IF(A2=1;0;IF(D2=D3;IF(C2=1;TRUE;FALSE);4))"; 

     /* 
     * INPUT 2 
     */ 
     String text = "=IF(A2=1;0;IF(D2=D3;IF(C2=1;TRUE;FALSE);TRUE))"; 

내 문제이며, 첫 번째 입력이 예상대로 작동하지만, TRUE 대신 마지막 요소 4 단지 다른 인 Input 2를 사용하는 경우, I

Exception in thread "main" java.lang.IllegalArgumentException: Tree must not already contain child D2=D3 
    at edu.uci.ics.jung.graph.DelegateTree.addChild(DelegateTree.java:182) 
    at edu.uci.ics.jung.graph.DelegateTree.addEdge(DelegateTree.java:102) 
    at edu.uci.ics.jung.graph.DelegateTree.addEdge(DelegateTree.java:346) 
    at edu.uci.ics.jung.graph.util.TreeUtils.growSubTree(TreeUtils.java:76) 
    at edu.uci.ics.jung.graph.util.TreeUtils.growSubTree(TreeUtils.java:80) 
    at edu.uci.ics.jung.graph.DelegateForest.getTrees(DelegateForest.java:295) 
    at edu.uci.ics.jung.graph.util.TreeUtils.getRoots(TreeUtils.java:34) 
    at edu.uci.ics.jung.algorithms.layout.TreeLayout.buildTree(TreeLayout.java:102) 
    at edu.uci.ics.jung.algorithms.layout.TreeLayout.<init>(TreeLayout.java:97) 
    at edu.uci.ics.jung.algorithms.layout.TreeLayout.<init>(TreeLayout.java:75) 
    at justDelete.me.codeTestingPackage.Test.<init>(Test.java:131) 
    at justDelete.me.codeTestingPackage.Test.main(Test.java:396) 

혼란스러운 것은 문자열이 올바르게 구문 분석과 같이 올바르게 프로그램에 의해 사용될 수 있다는 것입니다 :

[IF, A2=1, 0, IF, D2=D3, IF, C2=1, TRUE, FALSE, TRUE]

01 오류

@SuppressWarnings("serial") 
public class Test extends JApplet { 

    /** 
    * the graph 
    */ 
    Forest<String,Integer> graph; 


    private static final Logger log = Logger.getLogger(Test.class); 


    Factory<DirectedGraph<String,Integer>> graphFactory = 
      new Factory<DirectedGraph<String,Integer>>() { 

     public DirectedGraph<String, Integer> create() { 
      return new DirectedSparseMultigraph<String,Integer>(); 
     } 
    }; 

    Factory<Tree<String,Integer>> treeFactory = 
      new Factory<Tree<String,Integer>>() { 

     public Tree<String, Integer> create() { 
      return new DelegateTree<String,Integer>(graphFactory); 
     } 
    }; 



    Factory<Integer> edgeFactory = new Factory<Integer>() { 
     int i=0; 
     public Integer create() { 
      return i++; 
     }}; 

     Factory<String> vertexFactory = new Factory<String>() { 
      int i=0; 
      public String create() { 
       return "V"+i++; 
      }}; 

      /** 
      * the visual component and renderer for the graph 
      */ 
      VisualizationViewer<String,Integer> vv; 

      VisualizationServer.Paintable rings; 

      String root; 

      TreeLayout<String,Integer> layout; 
      @SuppressWarnings("unchecked") 
      FRLayout layout1; 

      TreeCollapser collapser; 

      RadialTreeLayout<String,Integer> radialLayout; 

      @SuppressWarnings("unchecked") 
      public Test() { 

       // create a simple graph for the demo 
       graph = new DelegateForest<String,Integer>(); 

       createTree(); 

       layout = new TreeLayout<String,Integer>(graph); 
       collapser = new TreeCollapser(); 

       radialLayout = new RadialTreeLayout<String,Integer>(graph); 
       radialLayout.setSize(new Dimension(600,600)); 
       vv = new VisualizationViewer<String,Integer>(layout, new Dimension(600,600)); 
       vv.setBackground(Color.white); 
       vv.getRenderContext().setEdgeShapeTransformer(new EdgeShape.Line()); 
       vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller()); 
       vv.getRenderContext().setVertexShapeTransformer(new ClusterVertexShapeFunction()); 
       // add a listener for ToolTips 
       vv.setVertexToolTipTransformer(new ToStringLabeller()); 
       vv.getRenderContext().setArrowFillPaintTransformer(new ConstantTransformer(Color.lightGray)); 
       rings = new Rings(); 

       Container content = getContentPane(); 
       final GraphZoomScrollPane panel = new GraphZoomScrollPane(vv); 
       content.add(panel); 

       final DefaultModalGraphMouse graphMouse = new DefaultModalGraphMouse(); 

       vv.setGraphMouse(graphMouse); 

       JComboBox modeBox = graphMouse.getModeComboBox(); 
       modeBox.addItemListener(graphMouse.getModeListener()); 
       graphMouse.setMode(ModalGraphMouse.Mode.TRANSFORMING); 

       final ScalingControl scaler = new CrossoverScalingControl(); 

       JButton plus = new JButton("+"); 
       plus.addActionListener(new ActionListener() { 
        public void actionPerformed(ActionEvent e) { 
         scaler.scale(vv, 1.1f, vv.getCenter()); 
        } 
       }); 
       JButton minus = new JButton("-"); 
       minus.addActionListener(new ActionListener() { 
        public void actionPerformed(ActionEvent e) { 
         scaler.scale(vv, 1/1.1f, vv.getCenter()); 
        } 
       }); 

       JToggleButton radial = new JToggleButton("Radial"); 
       radial.addItemListener(new ItemListener() { 

        public void itemStateChanged(ItemEvent e) { 
         if(e.getStateChange() == ItemEvent.SELECTED) { 
          //     layout.setRadial(true); 
          vv.setGraphLayout(radialLayout); 
          vv.getRenderContext().getMultiLayerTransformer().setToIdentity(); 
          vv.addPreRenderPaintable(rings); 
         } else { 
          //     layout.setRadial(false); 
          vv.setGraphLayout(layout); 
          vv.getRenderContext().getMultiLayerTransformer().setToIdentity(); 
          vv.removePreRenderPaintable(rings); 
         } 
         vv.repaint(); 
        }}); 

       JButton collapse = new JButton("Collapse"); 
       collapse.addActionListener(new ActionListener() { 

        public void actionPerformed(ActionEvent e) { 
         Collection picked =new HashSet(vv.getPickedVertexState().getPicked()); 
         if(picked.size() == 1) { 
          Object root = picked.iterator().next(); 
          Forest inGraph = (Forest)layout.getGraph(); 

          try { 
           collapser.collapse(vv.getGraphLayout(), inGraph, root); 
          } catch (InstantiationException e1) { 
           // TODO Auto-generated catch block 
           e1.printStackTrace(); 
          } catch (IllegalAccessException e1) { 
           // TODO Auto-generated catch block 
           e1.printStackTrace(); 
          } 

          vv.getPickedVertexState().clear(); 
          vv.repaint(); 
         } 
        }}); 

       JButton expand = new JButton("Expand"); 
       expand.addActionListener(new ActionListener() { 

        public void actionPerformed(ActionEvent e) { 
         Collection picked = vv.getPickedVertexState().getPicked(); 
         for(Object v : picked) { 
          if(v instanceof Forest) { 
           Forest inGraph = (Forest)layout.getGraph(); 
           collapser.expand(inGraph, (Forest)v); 
          } 
          vv.getPickedVertexState().clear(); 
          vv.repaint(); 
         } 
        }}); 

       JPanel scaleGrid = new JPanel(new GridLayout(1,0)); 
       scaleGrid.setBorder(BorderFactory.createTitledBorder("Zoom")); 

       JPanel controls = new JPanel(); 
       scaleGrid.add(plus); 
       scaleGrid.add(minus); 
       controls.add(radial); 
       controls.add(scaleGrid); 
       controls.add(modeBox); 
       controls.add(collapse); 
       controls.add(expand); 
       content.add(controls, BorderLayout.SOUTH); 
      } 

      class Rings implements VisualizationServer.Paintable { 

       Collection<Double> depths; 

       public Rings() { 
        depths = getDepths(); 
       } 

       private Collection<Double> getDepths() { 
        Set<Double> depths = new HashSet<Double>(); 
        Map<String,PolarPoint> polarLocations = radialLayout.getPolarLocations(); 
        for(String v : graph.getVertices()) { 
         PolarPoint pp = polarLocations.get(v); 
         depths.add(pp.getRadius()); 
        } 
        return depths; 
       } 

       public void paint(Graphics g) { 
        g.setColor(Color.lightGray); 

        Graphics2D g2d = (Graphics2D)g; 
        Point2D center = radialLayout.getCenter(); 

        Ellipse2D ellipse = new Ellipse2D.Double(); 
        for(double d : depths) { 
         ellipse.setFrameFromDiagonal(center.getX()-d, center.getY()-d, 
           center.getX()+d, center.getY()+d); 
         Shape shape = vv.getRenderContext(). 
           getMultiLayerTransformer().getTransformer(Layer.LAYOUT).transform(ellipse); 
         g2d.draw(shape); 
        } 
       } 

       public boolean useTransform() { 
        return true; 
       } 
      } 

      /** 
      * create Tree 
      */ 
      private void createTree() { 

       /* 
       * INPUT 1 
       */ 
//    String text = "=IF(A2=1;0;IF(D2=D3;IF(C2=1;TRUE;FALSE);4))"; 

       /* 
       * INPUT 2 
       */ 
       String text = "=IF(A2=1;0;IF(D2=D3;IF(C2=1;TRUE;FALSE);TRUE))"; 


       text.toUpperCase(); 

       //START 
       String[] operands = text.substring(1, text.length()).split("[;()]+"); 

       System.out.println(Arrays.toString(operands)); 
       int numIfs = operands.length/3; // actually (operands.length - 1)/3 but int division makes it the same 
       String[] nodes = new String[numIfs]; // stores the nodes (test strings) 
       int[] operandNos = new int[numIfs]; // stores the number of operands the if currently has 
       int nodesIndex = -1; // the index of the if node currently parsed 
       for (String s : operands) { 
        if (s.equals("IF")) { 
         // new if found -> increase position in the "stack" (nodes) 
         operandNos[++nodesIndex] = 0; 
        } else { 
         //      addVertex(s); 
         graph.addVertex(s); 
         switch (operandNos[nodesIndex]++) { 
         case 0: 
          // first operand = node name 
          nodes[nodesIndex] = s; 
          break; 
         case 1: 
          // second operand found -> add edge 
          graph.addEdge(edgeFactory.create(), s, nodes[nodesIndex]); 
          break; 
         case 2: 
          // last operand found -> add edge and go back 
          do { 
           graph.addEdge(edgeFactory.create(), s, nodes[nodesIndex]); 
           s = nodes[nodesIndex--]; 
          } while (nodesIndex >= 0 && operandNos[nodesIndex]++ == 2); 
          if (nodesIndex >= 0) { 
           // was not the last operand of the IF 
           graph.addEdge(edgeFactory.create(), s, nodes[nodesIndex]); 
          } 
         } 
        } 
       }  
       //END 

      } 

      class ClusterVertexShapeFunction<V> extends EllipseVertexShapeTransformer<V> 
      { 

       ClusterVertexShapeFunction() { 
        setSizeTransformer(new ClusterVertexSizeFunction<V>(20)); 
       } 
       @SuppressWarnings("unchecked") 
       @Override 
       public Shape transform(V v) { 
        if(v instanceof Graph) { 
         int size = ((Graph)v).getVertexCount(); 
         if (size < 8) { 
          int sides = Math.max(size, 3); 
          return factory.getRegularPolygon(v, sides); 
         } 
         else { 
          return factory.getRegularStar(v, size); 
         } 
        } 
        return super.transform(v); 
       } 
      } 

      /** 
      * A demo class that will make vertices larger if they represent 
      * a collapsed collection of original vertices 
      * @author Tom Nelson 
      * 
      * @param <V> 
      */ 
      class ClusterVertexSizeFunction<V> implements Transformer<V,Integer> { 
       int size; 
       public ClusterVertexSizeFunction(Integer size) { 
        this.size = size; 
       } 

       public Integer transform(V v) { 
        if(v instanceof Graph) { 
         return 30; 
        } 
        return size; 
       } 
      } 



      /** 
      * a driver for this demo 
      */ 
      public static void main(String[] args) { 
       JFrame frame = new JFrame(); 
       Container content = frame.getContentPane(); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

       content.add(new Test()); 
       frame.pack(); 
       frame.setVisible(true); 
      } 
} 

입력 2 코드를 실행, 내가 게시 된 오류 : 23,516,

여기에 주석 input 2 (이하 "깨진"입력)와 실행 가능한 내 프로그램의 버전입니다. 왜 그런지에 대한 모든 권고? 내 생각 엔 나무 줄기가 독특해야하기 때문에 일종의 우스꽝 스럽지만 문자열이 동일하다는 것입니다. 그러므로이 문제를 어떻게 다룰 것인가?

답변 해 주셔서 감사합니다.

답변

2

문제는 같은 정점이 여러 번 나타납니다.

세부 사항을 설명하면서 아주 멀리까지 갈 수 있지만 아이디어 만 내리면됩니다. JUNG의 그래프가 내부적으로 Map의 무리로 유지된다고 상상해보십시오. 예를 들어, Map<V, Set<E>>은 각 정점을이 정점에서 시작하는 가장자리 세트에 매핑합니다. 이제 정점의 유형을 String으로 정의했습니다. 그리고 동일한 String으로 식별되어야하는 여러 정점이있는 경우 특정 그래프 (트리이어야 함)가 일치하지 않을 수 있습니다.

더욱 암시 :

tree.getNode("A").addChild("TRUE"); 
tree.getNode("B").addChild("TRUE"); 

이 문자열 "TRUE"에 해당하는 노드가 부모, 즉 노드 "A"이됨을 의미와 :이처럼 보이는 트리를 만들려면 노드 "B". 귀하의 경우 실제 상황은 다르지만 파싱을 자세히 분석하지 않았습니다. 어떤 경우에도 메시지 "Tree에 이미 하위 D2가 포함되어 있으면 안됩니다. D3"은 "이런 종류의 문제"임을 나타냅니다.

약간의 불편 함이 있지만 그 해결책은 다소 간단합니다. 같은 문자열을 가진 정점이 여러 개있을 수 있으며 여전히 정점이 입니다. 특히 : 이 꼭지점의 equals 메소드는 객체가 실제로 별개의 꼭짓점 일 때 false을 반환해야합니다.

이것은 시뮬레이션을 도입하여 얻을 수 있습니다 ple Vertex 클래스.여기에서이 작업을 스케치하고 다시 시도해 보았습니다 : 아니요이 파서가 수행중인 작업을 분석하고 정점이 String s라고 가정되는 곳이 아직 있는지 여부를 신중히 확인해야합니다. 대신 Vertex 개체를 사용하도록 변경할 수 있습니다 (코드는 방법에 따라 정리가 필요할 수 있습니다). 그러나이 문제를 해결하기위한 기본 접근 방식을 보여 주어야합니다.

package stackoverflow; 

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Container; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.GridLayout; 
import java.awt.Shape; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.ItemEvent; 
import java.awt.event.ItemListener; 
import java.awt.geom.Ellipse2D; 
import java.awt.geom.Point2D; 
import java.util.Arrays; 
import java.util.Collection; 
import java.util.HashSet; 
import java.util.Map; 
import java.util.Set; 

import javax.swing.BorderFactory; 
import javax.swing.JApplet; 
import javax.swing.JButton; 
import javax.swing.JComboBox; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JToggleButton; 

import org.apache.commons.collections15.Factory; 
import org.apache.commons.collections15.Transformer; 
import org.apache.commons.collections15.functors.ConstantTransformer; 

import edu.uci.ics.jung.algorithms.layout.FRLayout; 
import edu.uci.ics.jung.algorithms.layout.PolarPoint; 
import edu.uci.ics.jung.algorithms.layout.RadialTreeLayout; 
import edu.uci.ics.jung.algorithms.layout.TreeLayout; 
import edu.uci.ics.jung.graph.DelegateForest; 
import edu.uci.ics.jung.graph.DelegateTree; 
import edu.uci.ics.jung.graph.DirectedGraph; 
import edu.uci.ics.jung.graph.DirectedSparseMultigraph; 
import edu.uci.ics.jung.graph.Forest; 
import edu.uci.ics.jung.graph.Graph; 
import edu.uci.ics.jung.graph.Tree; 
import edu.uci.ics.jung.visualization.GraphZoomScrollPane; 
import edu.uci.ics.jung.visualization.Layer; 
import edu.uci.ics.jung.visualization.VisualizationServer; 
import edu.uci.ics.jung.visualization.VisualizationViewer; 
import edu.uci.ics.jung.visualization.control.CrossoverScalingControl; 
import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse; 
import edu.uci.ics.jung.visualization.control.ModalGraphMouse; 
import edu.uci.ics.jung.visualization.control.ScalingControl; 
import edu.uci.ics.jung.visualization.decorators.EdgeShape; 
import edu.uci.ics.jung.visualization.decorators.EllipseVertexShapeTransformer; 
import edu.uci.ics.jung.visualization.decorators.ToStringLabeller; 
import edu.uci.ics.jung.visualization.subLayout.TreeCollapser; 

class Vertex 
{ 
    private static int IDCOUNTER = 0; 
    private final String name; 
    private final int id; 

    Vertex(String name) 
    { 
     this.name = name; 
     this.id = IDCOUNTER++; 
    } 

    String getName() 
    { 
     return name; 
    } 

    @Override 
    public String toString() 
    { 
     return name; 
    } 

    @Override 
    public int hashCode() 
    { 
     final int prime = 31; 
     int result = 1; 
     result = prime * result + id; 
     result = prime * result + ((name == null) ? 0 : name.hashCode()); 
     return result; 
    } 

    @Override 
    public boolean equals(Object obj) 
    { 
     if (this == obj) 
      return true; 
     if (obj == null) 
      return false; 
     if (getClass() != obj.getClass()) 
      return false; 
     Vertex other = (Vertex) obj; 
     if (id != other.id) 
      return false; 
     if (name == null) 
     { 
      if (other.name != null) 
       return false; 
     } 
     else if (!name.equals(other.name)) 
      return false; 
     return true; 
    } 

} 


@SuppressWarnings("serial") 
public class JUNGTree extends JApplet 
{ 

    /** 
    * the graph 
    */ 
    Forest<Vertex, Integer> graph; 

    Factory<DirectedGraph<Vertex, Integer>> graphFactory = 
     new Factory<DirectedGraph<Vertex, Integer>>() 
     { 

      public DirectedGraph<Vertex, Integer> create() 
      { 
       return new DirectedSparseMultigraph<Vertex, Integer>(); 
      } 
     }; 

    Factory<Tree<Vertex, Integer>> treeFactory = 
     new Factory<Tree<Vertex, Integer>>() 
     { 

      public Tree<Vertex, Integer> create() 
      { 
       return new DelegateTree<Vertex, Integer>(graphFactory); 
      } 
     }; 

    Factory<Integer> edgeFactory = new Factory<Integer>() 
    { 
     int i = 0; 

     public Integer create() 
     { 
      return i++; 
     } 
    }; 

    Factory<Vertex> vertexFactory = new Factory<Vertex>() 
    { 
     int i = 0; 

     public Vertex create() 
     { 
      return new Vertex("V" + i++); 
     } 
    }; 

    /** 
    * the visual component and renderer for the graph 
    */ 
    VisualizationViewer<Vertex, Integer> vv; 

    VisualizationServer.Paintable rings; 

    String root; 

    TreeLayout<Vertex, Integer> layout; 
    @SuppressWarnings("unchecked") 
    FRLayout layout1; 

    TreeCollapser collapser; 

    RadialTreeLayout<Vertex, Integer> radialLayout; 

    @SuppressWarnings("unchecked") 
    public JUNGTree() 
    { 

     // create a simple graph for the demo 
     graph = new DelegateForest<Vertex, Integer>(); 

     createTree(); 

     layout = new TreeLayout<Vertex, Integer>(graph); 
     collapser = new TreeCollapser(); 

     radialLayout = new RadialTreeLayout<Vertex, Integer>(graph); 
     radialLayout.setSize(new Dimension(600, 600)); 
     vv = 
      new VisualizationViewer<Vertex, Integer>(layout, new Dimension(600, 
       600)); 
     vv.setBackground(Color.white); 
     vv.getRenderContext().setEdgeShapeTransformer(new EdgeShape.Line()); 
     vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller()); 
     vv.getRenderContext().setVertexShapeTransformer(
      new ClusterVertexShapeFunction()); 
     // add a listener for ToolTips 
     vv.setVertexToolTipTransformer(new ToStringLabeller()); 
     vv.getRenderContext().setArrowFillPaintTransformer(
      new ConstantTransformer(Color.lightGray)); 
     rings = new Rings(); 

     Container content = getContentPane(); 
     final GraphZoomScrollPane panel = new GraphZoomScrollPane(vv); 
     content.add(panel); 

     final DefaultModalGraphMouse graphMouse = new DefaultModalGraphMouse(); 

     vv.setGraphMouse(graphMouse); 

     JComboBox modeBox = graphMouse.getModeComboBox(); 
     modeBox.addItemListener(graphMouse.getModeListener()); 
     graphMouse.setMode(ModalGraphMouse.Mode.TRANSFORMING); 

     final ScalingControl scaler = new CrossoverScalingControl(); 

     JButton plus = new JButton("+"); 
     plus.addActionListener(new ActionListener() 
     { 
      public void actionPerformed(ActionEvent e) 
      { 
       scaler.scale(vv, 1.1f, vv.getCenter()); 
      } 
     }); 
     JButton minus = new JButton("-"); 
     minus.addActionListener(new ActionListener() 
     { 
      public void actionPerformed(ActionEvent e) 
      { 
       scaler.scale(vv, 1/1.1f, vv.getCenter()); 
      } 
     }); 

     JToggleButton radial = new JToggleButton("Radial"); 
     radial.addItemListener(new ItemListener() 
     { 

      public void itemStateChanged(ItemEvent e) 
      { 
       if (e.getStateChange() == ItemEvent.SELECTED) 
       { 
        // layout.setRadial(true); 
        vv.setGraphLayout(radialLayout); 
        vv.getRenderContext().getMultiLayerTransformer() 
         .setToIdentity(); 
        vv.addPreRenderPaintable(rings); 
       } 
       else 
       { 
        // layout.setRadial(false); 
        vv.setGraphLayout(layout); 
        vv.getRenderContext().getMultiLayerTransformer() 
         .setToIdentity(); 
        vv.removePreRenderPaintable(rings); 
       } 
       vv.repaint(); 
      } 
     }); 

     JButton collapse = new JButton("Collapse"); 
     collapse.addActionListener(new ActionListener() 
     { 

      public void actionPerformed(ActionEvent e) 
      { 
       Collection picked = 
        new HashSet(vv.getPickedVertexState().getPicked()); 
       if (picked.size() == 1) 
       { 
        Object root = picked.iterator().next(); 
        Forest inGraph = (Forest) layout.getGraph(); 

        try 
        { 
         collapser.collapse(vv.getGraphLayout(), inGraph, root); 
        } 
        catch (InstantiationException e1) 
        { 
         // TODO Auto-generated catch block 
         e1.printStackTrace(); 
        } 
        catch (IllegalAccessException e1) 
        { 
         // TODO Auto-generated catch block 
         e1.printStackTrace(); 
        } 

        vv.getPickedVertexState().clear(); 
        vv.repaint(); 
       } 
      } 
     }); 

     JButton expand = new JButton("Expand"); 
     expand.addActionListener(new ActionListener() 
     { 

      public void actionPerformed(ActionEvent e) 
      { 
       Collection picked = vv.getPickedVertexState().getPicked(); 
       for (Object v : picked) 
       { 
        if (v instanceof Forest) 
        { 
         Forest inGraph = (Forest) layout.getGraph(); 
         collapser.expand(inGraph, (Forest) v); 
        } 
        vv.getPickedVertexState().clear(); 
        vv.repaint(); 
       } 
      } 
     }); 

     JPanel scaleGrid = new JPanel(new GridLayout(1, 0)); 
     scaleGrid.setBorder(BorderFactory.createTitledBorder("Zoom")); 

     JPanel controls = new JPanel(); 
     scaleGrid.add(plus); 
     scaleGrid.add(minus); 
     controls.add(radial); 
     controls.add(scaleGrid); 
     controls.add(modeBox); 
     controls.add(collapse); 
     controls.add(expand); 
     content.add(controls, BorderLayout.SOUTH); 
    } 

    class Rings implements VisualizationServer.Paintable 
    { 

     Collection<Double> depths; 

     public Rings() 
     { 
      depths = getDepths(); 
     } 

     private Collection<Double> getDepths() 
     { 
      Set<Double> depths = new HashSet<Double>(); 
      Map<Vertex, PolarPoint> polarLocations = 
       radialLayout.getPolarLocations(); 
      for (Vertex v : graph.getVertices()) 
      { 
       PolarPoint pp = polarLocations.get(v); 
       depths.add(pp.getRadius()); 
      } 
      return depths; 
     } 

     public void paint(Graphics g) 
     { 
      g.setColor(Color.lightGray); 

      Graphics2D g2d = (Graphics2D) g; 
      Point2D center = radialLayout.getCenter(); 

      Ellipse2D ellipse = new Ellipse2D.Double(); 
      for (double d : depths) 
      { 
       ellipse.setFrameFromDiagonal(center.getX() - d, center.getY() 
        - d, center.getX() + d, center.getY() + d); 
       Shape shape = 
        vv.getRenderContext().getMultiLayerTransformer() 
         .getTransformer(Layer.LAYOUT).transform(ellipse); 
       g2d.draw(shape); 
      } 
     } 

     public boolean useTransform() 
     { 
      return true; 
     } 
    } 

    /** 
    * create Tree 
    */ 
    private void createTree() 
    { 

     /* 
     * INPUT 1 
     */ 
     //String text = "=IF(A2=1;0;IF(D2=D3;IF(C2=1;TRUE;FALSE);4))"; 

     /* 
     * INPUT 2 
     */ 
     String text = "=IF(A2=1;0;IF(D2=D3;IF(C2=1;TRUE;FALSE);TRUE))"; 

     text.toUpperCase(); 

     // START 
     String[] operandStrings = text.substring(1, text.length()).split("[;()]+"); 

     Vertex[] operands = new Vertex[operandStrings.length]; 
     for (int i=0; i<operandStrings.length; i++) 
     { 
      operands[i] = new Vertex(operandStrings[i]); 
     } 

     System.out.println(Arrays.toString(operands)); 
     int numIfs = operands.length/3; // actually (operands.length - 1)/3 
              // but int division makes it the same 
     Vertex[] nodes = new Vertex[numIfs]; // stores the nodes (test strings) 
     int[] operandNos = new int[numIfs]; // stores the number of operands the 
              // if currently has 
     int nodesIndex = -1; // the index of the if node currently parsed 
     for (Vertex s : operands) 
     { 
      if (s.getName().equals("IF")) 
      { 
       // new if found -> increase position in the "stack" (nodes) 
       operandNos[++nodesIndex] = 0; 
      } 
      else 
      { 
       // addVertex(s); 
       graph.addVertex(s); 
       switch (operandNos[nodesIndex]++) 
       { 
        case 0: 
         // first operand = node name 
         nodes[nodesIndex] = s; 
         break; 
        case 1: 
         // second operand found -> add edge 
         graph.addEdge(edgeFactory.create(), s, 
          nodes[nodesIndex]); 
         break; 
        case 2: 
         // last operand found -> add edge and go back 
         do 
         { 
          graph.addEdge(edgeFactory.create(), s, 
           nodes[nodesIndex]); 
          s = nodes[nodesIndex--]; 
         } while (nodesIndex >= 0 
          && operandNos[nodesIndex]++ == 2); 
         if (nodesIndex >= 0) 
         { 
          // was not the last operand of the IF 
          graph.addEdge(edgeFactory.create(), s, 
           nodes[nodesIndex]); 
         } 
       } 
      } 
     } 
     // END 

    } 

    class ClusterVertexShapeFunction<V> extends 
     EllipseVertexShapeTransformer<V> 
    { 

     ClusterVertexShapeFunction() 
     { 
      setSizeTransformer(new ClusterVertexSizeFunction<V>(20)); 
     } 

     @SuppressWarnings("unchecked") 
     @Override 
     public Shape transform(V v) 
     { 
      if (v instanceof Graph) 
      { 
       int size = ((Graph) v).getVertexCount(); 
       if (size < 8) 
       { 
        int sides = Math.max(size, 3); 
        return factory.getRegularPolygon(v, sides); 
       } 
       else 
       { 
        return factory.getRegularStar(v, size); 
       } 
      } 
      return super.transform(v); 
     } 
    } 

    /** 
    * A demo class that will make vertices larger if they represent a collapsed 
    * collection of original vertices 
    * 
    * @author Tom Nelson 
    * 
    * @param <V> 
    */ 
    class ClusterVertexSizeFunction<V> implements Transformer<V, Integer> 
    { 
     int size; 

     public ClusterVertexSizeFunction(Integer size) 
     { 
      this.size = size; 
     } 

     public Integer transform(V v) 
     { 
      if (v instanceof Graph) 
      { 
       return 30; 
      } 
      return size; 
     } 
    } 

    /** 
    * a driver for this demo 
    */ 
    public static void main(String[] args) 
    { 
     JFrame frame = new JFrame(); 
     Container content = frame.getContentPane(); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     content.add(new JUNGTree()); 
     frame.pack(); 
     frame.setVisible(true); 
    } 
} 
관련 문제