#java #algorithm #jung #jung2
#java #алгоритм #jung #jung2
Вопрос:
Я создал следующую jung2
визуализацию. Мой код визуализирует текст в виде дерева. В основном я использую два входа, по одному за раз:
/*
* 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))";
Моя проблема в том, что первый ввод работает должным образом, но при использовании Input 2
, который просто отличается в последнем элементе 4
вместо TRUE
, я получаю ошибку:
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]
Вот версия моей программы, которая может быть запущена с input 2
(«сломанным» вводом) в комментариях:
@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 amp;amp; 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 я получаю сообщение об ошибке. Какие-либо рекомендации, почему это так? Я предполагаю, что строки одинаковы, хотя это было бы нелепо, потому что листья дерева должны быть уникальными. Следовательно, как справиться с этой проблемой?
Я ценю ваш ответ!
Ответ №1:
Проблема в том, что одна и та же вершина должна появляться несколько раз.
Можно было бы зайти очень далеко с объяснением деталей, но просто для того, чтобы дать идею: представьте, что граф в JUNG внутренне поддерживается как набор Map
s. Например, a Map<V, Set<E>>
, который сопоставляет каждую вершину с набором ребер, которые начинаются с этой вершины. Теперь вы определили тип вершины, который должен быть String
. И когда есть несколько вершин, которые должны быть идентифицированы одним и тем же String
, тогда конкретный граф (который должен быть деревом) может стать непоследовательным.
Еще более наводящий на размышления: вы хотите создать дерево, которое выглядит следующим образом:
tree.getNode("A").addChild("TRUE");
tree.getNode("B").addChild("TRUE");
Это означало бы, что узел, соответствующий строке "TRUE"
, будет иметь двух родителей, а именно узел "A"
и узел "B"
. (Фактическая ситуация в вашем случае иная, но я не анализировал синтаксический анализ подробно — в любом случае сообщение «Дерево не должно уже содержать дочерний элемент D2 = D3» указывает, что это «проблема такого рода».
Решение для этого довольно простое, хотя оно может быть немного неудобным: Вы должны убедиться, что может быть несколько вершин с одной и той же строкой, которые по-прежнему считаются разными вершинами. В частности: equals
метод этих вершин должен возвращать false
, когда объекты должны фактически быть отдельными вершинами.
Это может быть достигнуто путем введения простого 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 resu<
}
@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
amp;amp; 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);
}
}