edu.uci.ics.jung.visualization3d.VisualizationViewer.java Source code

Java tutorial

Introduction

Here is the source code for edu.uci.ics.jung.visualization3d.VisualizationViewer.java

Source

/*
 * Copyright (c) 2003, the JUNG Project and the Regents of the University of
 * California All rights reserved.
 * 
 * This software is open-source under the BSD license; see either "license.txt"
 * or http://jung.sourceforge.net/license.txt for a description.
 */
package edu.uci.ics.jung.visualization3d;

/**
 * 
 */
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.GraphicsConfiguration;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.HashMap;
import java.util.Map;

import javax.media.j3d.AmbientLight;
import javax.media.j3d.Appearance;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.Bounds;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.DirectionalLight;
import javax.media.j3d.Font3D;
import javax.media.j3d.FontExtrusion;
import javax.media.j3d.Group;
import javax.media.j3d.Material;
import javax.media.j3d.Node;
import javax.media.j3d.OrientedShape3D;
import javax.media.j3d.Text3D;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.swing.JPanel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.vecmath.Color3f;
import javax.vecmath.Point3d;
import javax.vecmath.Point3f;
import javax.vecmath.Vector3f;

import org.apache.commons.collections15.BidiMap;
import org.apache.commons.collections15.bidimap.DualHashBidiMap;

import com.sun.j3d.utils.behaviors.mouse.MouseWheelZoom;
import com.sun.j3d.utils.geometry.Primitive;
import com.sun.j3d.utils.picking.PickTool;
import com.sun.j3d.utils.picking.behaviors.PickingCallback;
import com.sun.j3d.utils.universe.SimpleUniverse;

import edu.uci.ics.jung.algorithms.layout.util.VisRunner;
import edu.uci.ics.jung.algorithms.layout3d.Layout;
import edu.uci.ics.jung.algorithms.util.IterativeContext;
import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.graph.util.Context;
import edu.uci.ics.jung.graph.util.Pair;
import edu.uci.ics.jung.visualization.picking.MultiPickedState;
import edu.uci.ics.jung.visualization.picking.PickedState;
import edu.uci.ics.jung.visualization3d.control.MouseRotate;
import edu.uci.ics.jung.visualization3d.control.MouseTranslate;
import edu.uci.ics.jung.visualization3d.control.PickSphereBehavior;
import edu.uci.ics.jung.visualization3d.control.PickTranslateBehavior;
import edu.uci.ics.jung.visualization3d.layout.LayoutEventBroadcaster;

/**
 * 
 * @author Tom Nelson - tomnelson@dev.java.net
 *
 */
public class VisualizationViewer<V, E> extends JPanel {

    BranchGroup objRoot;
    TransformGroup objTrans;
    //   Appearance vertexLook;
    //   Appearance edgeLook;
    Appearance grayLook;
    /**
     * a listener used to cause pick events to result in
     * repaints, even if they come from another view
     */
    protected ItemListener pickEventListener;
    /**
     * holds the state of which vertices of the graph are
     * currently 'picked'
     */
    protected PickedState<V> pickedVertexState;

    /**
     * holds the state of which edges of the graph are
     * currently 'picked'
     */
    protected PickedState<E> pickedEdgeState;

    protected RenderContext<V, E> renderContext = new PluggableRenderContext<V, E>();

    BidiMap<V, VertexGroup> vertexMap = new DualHashBidiMap<V, VertexGroup>();
    Map<E, EdgeGroup> edgeMap = new HashMap<E, EdgeGroup>();
    Graph<V, E> graph;
    Layout<V, E> layout;

    public VisualizationViewer() {
        //      controls = createControls();
        setLayout(new BorderLayout());

        renderContext.setPickedVertexState(new MultiPickedState<V>());
        renderContext.setPickedEdgeState(new MultiPickedState<E>());
        GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration();
        final Canvas3D c = new Canvas3D(config);
        add(c, BorderLayout.CENTER);
        setPickedVertexState(new MultiPickedState<V>());
        setPickedEdgeState(new MultiPickedState<E>());

        // Create a SpringGraph scene and attach it to the virtual universe
        BranchGroup scene = createSceneGraph(c);
        SimpleUniverse u = new SimpleUniverse(c);
        u.getViewer().getView().setUserHeadToVworldEnable(true);

        // This will move the ViewPlatform back a bit so the
        // objects in the scene can be viewed.
        u.getViewingPlatform().setNominalViewingTransform();

        u.addBranchGraph(scene);
    }

    public Layout<V, E> getGraphLayout() {
        return layout;
    }

    public BranchGroup createSceneGraph(final Canvas3D canvas) {

        objRoot = new BranchGroup();
        objRoot.setCapability(Group.ALLOW_CHILDREN_EXTEND);
        objRoot.setCapability(Group.ALLOW_CHILDREN_WRITE);

        TransformGroup objScale = new TransformGroup();
        Transform3D t3d = new Transform3D();
        //      t3d.setScale(0.05);
        objScale.setTransform(t3d);
        objRoot.addChild(objScale);

        Transform3D tt = new Transform3D();
        tt.setScale(.05);
        tt.setTranslation(new Vector3f(0, 0, -30.f));
        objTrans = new TransformGroup(tt);
        objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
        objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
        objTrans.setCapability(TransformGroup.ALLOW_CHILDREN_EXTEND);
        objScale.addChild(objTrans);
        //      objRoot.addChild(objTrans);

        // Create Colors, Materials,  and Appearances.
        Appearance look = new Appearance();
        Color3f objColor = new Color3f(0.7f, 0.7f, 0.7f);
        Color3f black = new Color3f(0.f, 0.f, 0.f);
        Color3f white = new Color3f(1.0f, 1.0f, 0.6f);
        Color3f gray = new Color3f(.2f, .2f, .2f);
        Color3f red = new Color3f(1.0f, 0, 0);
        Color3f yellow = new Color3f(1, 1, 0);

        Material objMaterial = new Material(objColor, black, objColor, white, 100.0f);
        Material blackMaterial = new Material(objColor, black, black, objColor, 10.0f);
        Material whiteMaterial = new Material(white, white, white, white, 100.0f);
        Material grayMaterial = new Material(gray, black, gray, gray, 100.0f);

        Material redMaterial = new Material(red, black, red, red, 100.0f);
        Material yellowMaterial = new Material(yellow, black, yellow, yellow, 100);

        look.setMaterial(new Material(objColor, black, objColor, white, 100.0f));
        Appearance blackLook = new Appearance();
        blackLook.setMaterial(blackMaterial);

        Appearance whiteLook = new Appearance();
        whiteLook.setMaterial(whiteMaterial);

        Appearance grayLook = new Appearance();
        grayLook.setMaterial(grayMaterial);
        grayLook.setCapability(Appearance.ALLOW_MATERIAL_READ);
        grayLook.setCapability(Appearance.ALLOW_MATERIAL_WRITE);

        final Appearance redLook = new Appearance();
        redLook.setMaterial(redMaterial);
        //      vertexLook = redLook;

        Appearance objLook = new Appearance();
        objLook.setMaterial(objMaterial);
        grayLook = objLook;
        final Appearance yellowLook = new Appearance();
        yellowLook.setMaterial(yellowMaterial);
        Bounds bounds = new BoundingSphere(new Point3d(), 300);

        MouseRotate behavior1 = new MouseRotate();
        behavior1.setTransformGroup(objTrans);
        objTrans.addChild(behavior1);
        behavior1.setSchedulingBounds(bounds);

        MouseWheelZoom behavior2 = new MouseWheelZoom();
        behavior2.setTransformGroup(objTrans);
        //      behavior2.setFactor(10);
        objTrans.addChild(behavior2);
        behavior2.setSchedulingBounds(bounds);

        MouseTranslate behavior3 = new MouseTranslate();
        behavior3.setTransformGroup(objTrans);
        objTrans.addChild(behavior3);
        behavior3.setSchedulingBounds(bounds);

        PickTranslateBehavior ptb = new PickTranslateBehavior(objRoot, canvas, bounds, PickTool.GEOMETRY);
        ptb.setSchedulingBounds(bounds);
        //      objTrans.addChild(ptb);
        ptb.setupCallback(new PickingCallback() {

            public void transformChanged(int type, TransformGroup tg) {
                if (tg == null)
                    return;
                Transform3D t3d = new Transform3D();
                tg.getTransform(t3d);
                //            System.err.println(tg+" transformChanged \n"+t3d);
                Point3f p1 = new Point3f();
                V v = vertexMap.getKey(tg);
                //            Transform3D lvw = new Transform3D();
                //            tg.getLocalToVworld(lvw);
                //            System.err.println("lvw = \n"+lvw);
                //            lvw.invert();
                //            System.err.println("invert lvw = \n"+lvw);
                Point3f p0 = layout.transform(v);
                //            Transform3D vwip = new Transform3D();
                //            canvas.getVworldToImagePlate(vwip);
                //            System.err.println("vwip=\n"+vwip);
                //            t3d.mul(lvw);
                t3d.transform(p1);
                //            scale.transform(p1);
                System.err.println(
                        "change location for vertex " + v + ", transformGroup " + tg + " from " + p0 + " to " + p1);
                //            p1.set(p1.getX()*2,p1.getY()*2,p1.getZ()*2);
                //            layout.setLocation(v, p1);

            }
        });

        PickSphereBehavior psb = new PickSphereBehavior(objRoot, canvas, bounds);

        PickVertexBehavior pvb = new PickVertexBehavior(objRoot, canvas, bounds,
                renderContext.getPickedVertexState());
        objTrans.addChild(pvb);
        pvb.addChangeListener(new ChangeListener() {

            public void stateChanged(ChangeEvent e) {
                for (V v : graph.getVertices()) {
                    VertexGroup<V> vg = vertexMap.get(v);
                    Appearance look = redLook;
                    if (renderContext.getPickedVertexState().isPicked(v)) {
                        look = yellowLook;
                    }
                    Node node = vg.getShape();
                    if (node instanceof Primitive) {
                        ((Primitive) node).setAppearance(look);
                    }
                }

            }
        });

        //Shine it with two colored lights.
        Color3f lColor1 = new Color3f(.5f, .5f, .5f);
        Color3f lColor2 = new Color3f(1.0f, 1.0f, 1.0f);
        Vector3f lDir2 = new Vector3f(-1.0f, 0.0f, -1.0f);
        DirectionalLight lgt2 = new DirectionalLight(lColor2, lDir2);
        AmbientLight ambient = new AmbientLight(lColor1);
        lgt2.setInfluencingBounds(bounds);
        ambient.setInfluencingBounds(bounds);
        objRoot.addChild(lgt2);
        objRoot.addChild(ambient);

        // Let Java 3D perform optimizations on this scene graph.
        objRoot.compile();

        //      VisRunner runner = new VisRunner((IterativeContext)elayout);
        //      runner.relax();

        return objRoot;
    }

    public void setGraphLayout(Layout<V, E> inLayout) {

        //      this.layout = inLayout;
        this.graph = inLayout.getGraph();
        BranchGroup branch = new BranchGroup();
        LayoutEventBroadcaster<V, E> elayout = new LayoutEventBroadcaster<V, E>(inLayout);
        this.layout = elayout;
        for (V v : graph.getVertices()) {
            VertexGroup<V> vg = new VertexGroup<V>(v, renderContext.getVertexShapeTransformer().transform(v));
            vg.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
            vg.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
            vertexMap.put(v, vg);
            branch.addChild(vg);
            String label = renderContext.getVertexStringer().transform(v);
            if (label != null) {
                String fontName = "Serif";
                Font3D f3d = new Font3D(new Font(fontName, Font.PLAIN, 2), new FontExtrusion());
                Text3D txt = new Text3D(f3d, label, new Point3f(2f, 2f, 0));
                OrientedShape3D textShape = new OrientedShape3D();
                textShape.setGeometry(txt);
                textShape.setAppearance(grayLook);
                //            textShape.setAlignmentAxis( 0.0f, 1.0f, 0.0f);
                textShape.setAlignmentMode(OrientedShape3D.ROTATE_ABOUT_POINT);
                textShape.setRotationPoint(new Point3f());
                //            objScale.addChild( textShape );
                //            BranchGroup bg = new BranchGroup();
                //            bg.addChild(textShape);
                //            branch.addChild(bg);

                //            Text2D text = new Text2D(label+" more text here", new Color3f(0,0,0),"Serif",50,Font.BOLD);
                Transform3D tt = new Transform3D();
                //            tt.setTranslation(new Vector3f(100,100,100));
                tt.setScale(5);
                TransformGroup tg = new TransformGroup(tt);
                //            textShape.setGeometry(text);
                tg.addChild(textShape);
                BranchGroup bg = new BranchGroup();
                bg.addChild(tg);
                //            branch.addChild(bg);
                vg.getLabelNode().addChild(bg);

            }

        }
        System.err.println("vertexMap = " + vertexMap);

        for (E edge : graph.getEdges()) {
            EdgeGroup<E> eg = new EdgeGroup<E>(edge, renderContext.getEdgeShapeTransformer()
                    .transform(Context.<Graph<V, E>, E>getInstance(graph, edge)));
            eg.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
            eg.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
            edgeMap.put(edge, eg);
            branch.addChild(eg);
        }

        //      System.err.println("branch is "+branch);
        //      for(int i=0; i<branch.numChildren(); i++) {
        //         System.err.println("branch child ["+i+"] is "+branch.getChild(i));
        //      }

        objTrans.addChild(branch);
        elayout.addChangeListener(new ChangeListener() {

            public void stateChanged(ChangeEvent e) {
                for (V v : vertexMap.keySet()) {
                    Point3f p = VisualizationViewer.this.layout.transform(v);
                    Vector3f pv = new Vector3f(p.getX(), p.getY(), p.getZ());
                    Transform3D tx = new Transform3D();
                    tx.setTranslation(pv);
                    vertexMap.get(v).setTransform(tx);
                }

                for (E edge : graph.getEdges()) {
                    Pair<V> endpoints = graph.getEndpoints(edge);
                    V start = endpoints.getFirst();
                    V end = endpoints.getSecond();
                    EdgeGroup eg = edgeMap.get(edge);
                    eg.setEndpoints(layout.transform(start), layout.transform(end));
                }
            }
        });

        elayout.setSize(new BoundingSphere(new Point3d(), 200));
        elayout.initialize();
        VisRunner runner = new VisRunner((IterativeContext) elayout);
        runner.relax();

        //      for(int i=0; i<objTrans.numChildren(); i++) {
        //         System.err.println("objTrans child ["+i+"] is "+objTrans.getChild(i));
        //      }

    }

    public void setPickedVertexState(PickedState<V> pickedVertexState) {
        if (pickEventListener != null && this.pickedVertexState != null) {
            this.pickedVertexState.removeItemListener(pickEventListener);
        }
        this.pickedVertexState = pickedVertexState;
        this.renderContext.setPickedVertexState(pickedVertexState);
        if (pickEventListener == null) {
            pickEventListener = new ItemListener() {

                public void itemStateChanged(ItemEvent e) {
                    System.err.println(e.getItem() + " was picked");
                }
            };
        }
        pickedVertexState.addItemListener(pickEventListener);
    }

    /* (non-Javadoc)
     * @see edu.uci.ics.jung.visualization.VisualizationServer#setPickedEdgeState(edu.uci.ics.jung.visualization.picking.PickedState)
     */
    public void setPickedEdgeState(PickedState<E> pickedEdgeState) {
        if (pickEventListener != null && this.pickedEdgeState != null) {
            this.pickedEdgeState.removeItemListener(pickEventListener);
        }
        this.pickedEdgeState = pickedEdgeState;
        this.renderContext.setPickedEdgeState(pickedEdgeState);
        if (pickEventListener == null) {
            pickEventListener = new ItemListener() {

                public void itemStateChanged(ItemEvent e) {
                    repaint();
                }
            };
        }
        pickedEdgeState.addItemListener(pickEventListener);
    }

    /**
     * @return the renderContext
     */
    public RenderContext<V, E> getRenderContext() {
        return renderContext;
    }

    //   public static void main(String argv[])
    //   {
    //      final VisualizationViewer enigma = new VisualizationViewer();
    //      JFrame f = new JFrame();
    //      f.add(enigma);
    //      f.setSize(600,600);
    //      f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    ////         new MainFrame(enigma, 500, 500);
    ////      f.pack();
    //      f.setVisible(true);
    //   }
}