Reputation: 2074
I am trying to use Jung for a project and to get the look/behavior I want I am starting with some test data.
The idea is to have very Large Vertices with labels on top of the Verticies shapes. The data for the graph will be generated at runtime so I cannot do a static layout.
How do I layout the graph so that the Vertices do not overlap, but are still large enough so that the labels fit inside (real label will have longer strings 20-30 chars). I have tried using SpringLayout but the nodes still overlap, additionally the layout keeps jiggling (which is annoying).
I also tried FRLayout while increassing the Repulsion multiplier, however after the number gets large enough it just creates a circle with the Vertices overlapping.
If I Zoom in using the mouse gestures the nodes seem to separate and I get a view closer to what I want. So maybe the solution involves zooming in at initialization, just not sure exactly how to do that and how to decide how much to zoom as it may be dependent on the number of nodes.
In general my data will have a small number of nodes (less then 50 and more commonly less then 10). However it is data driven so I don't have total control over those sizes.
Finally when the graph does show up it is also partially off the screen. Ideally it would render toward the top left portion of the viewable area. Is there a way to control that?
Below is the sample class I am working with to better show what I mean (trimmed for release).
import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.graph.util.TestGraphs;
import edu.uci.ics.jung.visualization.VisualizationViewer;
import edu.uci.ics.jung.algorithms.layout.AbstractLayout;
import edu.uci.ics.jung.algorithms.layout.SpringLayout;
import edu.uci.ics.jung.visualization.GraphZoomScrollPane;
import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse;
import edu.uci.ics.jung.visualization.control.ModalGraphMouse;
import edu.uci.ics.jung.visualization.decorators.AbstractVertexShapeTransformer;
import edu.uci.ics.jung.visualization.decorators.EdgeShape;
import edu.uci.ics.jung.visualization.decorators.ToStringLabeller;
import java.awt.BorderLayout;
import java.awt.Color;
import org.apache.commons.collections15.Transformer;
import org.apache.commons.collections15.functors.ConstantTransformer;
import edu.uci.ics.jung.visualization.picking.PickedState;
import edu.uci.ics.jung.visualization.renderers.DefaultVertexLabelRenderer;
import edu.uci.ics.jung.visualization.renderers.GradientVertexRenderer;
import edu.uci.ics.jung.visualization.renderers.VertexLabelAsShapeRenderer;
import java.awt.*;
public class IDRelationshipGraphPanel extends javax.swing.JPanel
{
private final VisualizationViewer<Integer,Number> vv;
protected Transformer<Integer,String> vs;
protected DefaultModalGraphMouse<Integer, Number> gm;
protected AbstractLayout layout;
protected VertexShapeSizeAspect<Integer,Number> vssa;
public IDRelationshipGraphPanel()
{
Graph<? extends Object, ? extends Object> g = TestGraphs.getOneComponentGraph();
layout = new SpringLayout( g) ;
vv= new VisualizationViewer<Integer,Number>(layout);
GraphZoomScrollPane scrollPane = new GraphZoomScrollPane(vv);
gm = new DefaultModalGraphMouse<Integer, Number>();
vv.setGraphMouse(gm);
add(scrollPane, BorderLayout.CENTER);
PickedState<Integer> picked_state = vv.getPickedVertexState();
VertexLabelAsShapeRenderer<Integer, Number> vlasr = new VertexLabelAsShapeRenderer<Integer, Number>(vv.getRenderContext());
vv.getRenderContext().setVertexShapeTransformer(vlasr);
vv.getRenderContext().setVertexLabelRenderer(new DefaultVertexLabelRenderer(Color.red));
vv.getRenderContext().setEdgeStrokeTransformer(new ConstantTransformer(new BasicStroke(2.5f)));
// customize the renderer
vv.getRenderer().setVertexRenderer(new GradientVertexRenderer<Integer, Number>( new Color(175,224,228), new Color(133,170,173), true));
vv.getRenderer().setVertexLabelRenderer(vlasr);
vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller<Integer>());
vv.getRenderContext().setEdgeShapeTransformer(new EdgeShape.Line<Integer, Number>());
vssa = new VertexShapeSizeAspect<Integer,Number>();
vv.getRenderContext().setVertexShapeTransformer(vssa);
vv.getRenderContext().setArrowFillPaintTransformer(new ConstantTransformer(Color.lightGray));
vv.getRenderContext().setArrowDrawPaintTransformer(new ConstantTransformer(Color.black));
}
private final static class VertexShapeSizeAspect<V,E>
extends AbstractVertexShapeTransformer <V>
implements Transformer<V,Shape> {
public VertexShapeSizeAspect()
{
setSizeTransformer(new Transformer<V,Integer>()
{
public Integer transform(V v)
{
return 150;
}
});
setAspectRatioTransformer(new Transformer<V,Float>()
{
public Float transform(V v)
{
return 1.0f;
}
});
}
public Shape transform(V v){return factory.getEllipse(v);}
}
}
Overlapping Verticies with Spring Layout
Zoom in of Spring Layout appears better
Upvotes: 3
Views: 1735
Reputation: 21
For node spacing, there is a setForceMultiplier and setRepulsionRange that will help in determining how far apart the nodes are drawn. To get rid of the "jiggle", do layout.lock(true) to keep the nodes in place once they are where you want them.
Upvotes: 2