All Downloads are FREE. Search and download functionalities are using the official Maven repository.

edu.uci.ics.jung.visualization3d.VisualizationViewer Maven / Gradle / Ivy

There is a newer version: 2.0.1
Show newest version
/*
 * 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 - [email protected]
 *
 */
public class VisualizationViewer 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 pickedVertexState;
	
	/**
	 * holds the state of which edges of the graph are
	 * currently 'picked'
	 */
    protected PickedState pickedEdgeState;
    
    protected RenderContext renderContext = new PluggableRenderContext();

	BidiMap vertexMap = new DualHashBidiMap();
	Map edgeMap = new HashMap();
	Graph graph;
	Layout layout;

	public VisualizationViewer() {
//		controls = createControls();
		setLayout(new BorderLayout());
		
		renderContext.setPickedVertexState(new MultiPickedState());
		renderContext.setPickedEdgeState(new MultiPickedState());
		GraphicsConfiguration config = 
			SimpleUniverse.getPreferredConfiguration();
		final Canvas3D c = new Canvas3D(config);
		add(c, BorderLayout.CENTER);
		setPickedVertexState(new MultiPickedState());
		setPickedEdgeState(new MultiPickedState());

		// 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 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 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 inLayout) {

//		this.layout = inLayout;
		this.graph = inLayout.getGraph();
		BranchGroup branch = new BranchGroup();
		LayoutEventBroadcaster elayout =
			new LayoutEventBroadcaster(inLayout);
		this.layout = elayout;
		for(V v : graph.getVertices()) {
			VertexGroup vg = new VertexGroup(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 eg = 
				new EdgeGroup(edge, renderContext.getEdgeShapeTransformer().transform(Context.,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 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 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 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 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);
//	}
}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy