views:

321

answers:

1

Hello,

I'm using JUNG ( http://jung.sourceforge.net/index.html ) to draw graphics in java. The software is great but I have a small question. How can I be sure that the displayed graph is each time the same (no changes is architecture or position)?

To be more specific: the graph model (data to be represented) doesn't change but its representation changes each time I hit the "View graph" button :) [some vertices are in other places, for example: sometimes in the upper part of the window, sometimes in the lower part ]

Thank you,

Iulian

+1  A: 

A StaticLayout lets you specify a vertex to Point2D transformer. This will allow you to control where the vertices are placed and should do what you want to do. You should use the following constructor:

public StaticLayout(Graph<V,E> graph,
                org.apache.commons.collections15.Transformer<V,Point2D> initializer)

You'll need to implement your own transformer that takes in a vertex and returns the location where the vertex should appear. An example of its in use:

package test;

import java.awt.Dimension;
import java.awt.geom.Point2D;
import java.io.IOException;

import javax.swing.JFrame;

import org.apache.commons.collections15.Transformer;

import edu.uci.ics.jung.algorithms.layout.StaticLayout;
import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.graph.SparseMultigraph;
import edu.uci.ics.jung.visualization.VisualizationViewer;

/**
 * Jung example - vertices appearing in same location
 * 
 * @author Kah
 */
public class StaticLocation {

    /**
     * @param args
     * @throws IOException
     */
    public static void main(String[] args) throws IOException {
        // Setup the example graph.
        Graph<Integer, String> basis = new SparseMultigraph<Integer, String>();
        basis.addVertex(Integer.valueOf(0));
        basis.addVertex(Integer.valueOf(1));
        basis.addVertex(Integer.valueOf(2));
        basis.addEdge("Edge 1", Integer.valueOf(0), Integer.valueOf(1));
        basis.addEdge("Edge 2", Integer.valueOf(0), Integer.valueOf(2));
        basis.addEdge("Edge 3", Integer.valueOf(1), Integer.valueOf(2));

        Transformer<Integer, Point2D> locationTransformer = new Transformer<Integer, Point2D>() {

            @Override
            public Point2D transform(Integer vertex) {
                int value = (vertex.intValue() * 40) + 20;
                return new Point2D.Double((double) value, (double) value);
            }
        };

        StaticLayout<Integer, String> layout = new StaticLayout<Integer, String>(
                basis, locationTransformer);
        layout.setSize(new Dimension(250, 250));
        VisualizationViewer<Integer, String> vv = new VisualizationViewer<Integer, String>(
                layout);

        vv.setPreferredSize(new Dimension(250, 250));

        JFrame frame = new JFrame("Simple Graph View 2");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(vv);
        vv.setOpaque(false);
        frame.pack();
        frame.setVisible(true);
    }
}

Added 20 Feb 2010:

An alternative is to use a PersistentLayoutImpl to save the locations of the vertices to a file. However, you need to also somehow persist the graph to get which vertices and vertices were on there (this needs to persisted separately). There are number of classes for persisting the graph in edu.uci.ics.jung.io. This is an example that uses just PersistentLayoutImpl:

package test;

import java.awt.Dimension;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

import javax.swing.JFrame;

import org.apache.commons.collections15.Transformer;

import edu.uci.ics.jung.algorithms.layout.Layout;
import edu.uci.ics.jung.algorithms.layout.SpringLayout2;
import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.graph.SparseMultigraph;
import edu.uci.ics.jung.io.GraphMLReader;
import edu.uci.ics.jung.io.GraphMLWriter;
import edu.uci.ics.jung.visualization.VisualizationViewer;
import edu.uci.ics.jung.visualization.decorators.ToStringLabeller;
import edu.uci.ics.jung.visualization.layout.PersistentLayoutImpl;

/**
 * Jung example - vertices appearing in same location
 * 
 * @author Kah
 */
public class PersistentVertices
{

    /**
     * @param args
     * @throws IOException
     */
    public static void main(String[] args) throws IOException
    {
        // Setup the example graph.
        try
        {
            VisualizationViewer<Integer, String> vv = new VisualizationViewer<Integer, String>(
                    getLayout());

            vv.setPreferredSize(new Dimension(250, 250));

            JFrame frame = new JFrame("Simple Graph View 2");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.getContentPane().add(vv);
            vv.setOpaque(false);
            frame.pack();
            frame.setVisible(true);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    private static Layout<Integer, String> getLayout() throws IOException,
            ClassNotFoundException
    {
        Graph<Integer, String> graph = new SparseMultigraph<Integer, String>();
        File source = new File("C:\\layout.dat");
        SpringLayout2<Integer, String> backing = new SpringLayout2<Integer, String>(
                graph);
        PersistentLayoutImpl<Integer, String> layout = new PersistentLayoutImpl<Integer, String>(
                backing);
        layout.setSize(new Dimension(250, 250));

        // Note that you also need to put the vertices and edges back before
        // restoring.
        graph.addVertex(Integer.valueOf(0));
        graph.addVertex(Integer.valueOf(1));
        graph.addVertex(Integer.valueOf(2));
        graph.addEdge("Edge 1", Integer.valueOf(0), Integer.valueOf(1));
        graph.addEdge("Edge 2", Integer.valueOf(0), Integer.valueOf(2));
        graph.addEdge("Edge 3", Integer.valueOf(1), Integer.valueOf(2));

        if (source.exists())
        {
            layout.restore(source.getAbsolutePath());
        }
        else
        {
            layout.persist(source.getAbsolutePath());
        }
        return layout;
    }
}

Note that the example does not persist the vertices and edges yet, as I haven't had the time to figure out how use the classes in edu.uci.ics.jung.io yet.

Klarth
This means that I have to reposition all the points by myself?I have some complex graph architecture that needs to be visualized and I'm not sure if I can "tell" the right position of each vertex.
Iulian Şerbănoiu
No you don't have to reposition the points by yourself. You can use a PersistentLayout to use another layout and then save it. Please see my revised answer (I added something new).
Klarth
I was hoping to avoid that but that's life. I really think this is the best choice. Thank you, Klarth.
Iulian Şerbănoiu