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

edu.uci.ics.jung.algorithms.layout3d.AbstractLayout 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.
 * 
 * Created on Jul 7, 2003
 * 
 */
package edu.uci.ics.jung.algorithms.layout3d;

import java.util.Collection;
import java.util.ConcurrentModificationException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.media.j3d.BoundingSphere;
import javax.vecmath.Point3f;

import org.apache.commons.collections15.Transformer;
import org.apache.commons.collections15.map.LazyMap;

import edu.uci.ics.jung.graph.Graph;

/**
 * Implements some of the dirty work of writing a layout algorithm, allowing
 * the user to express their major intent more simply. When writing a Layout,
 * there are many shared tasks: handling tracking locked nodes, applying
 * filters, and tracing nearby vertices. This package automates all of those.
 * 
 * @author Danyel Fisher, Scott White
 * @param 
 */
public abstract class AbstractLayout implements Layout {

    /**
     * a set of vertices that should not move in relation to the
     * other vertices
     */
	private Set dontmove = new HashSet();

	private BoundingSphere size;
	private Graph graph;
    
    protected Map locations = 
    	LazyMap.decorate(new HashMap(),
    			new Transformer() {
					public Point3f transform(V arg0) {
						return new Point3f();
					}});


	/**
	 * Constructor. Initializes the current size to be 100x100, both the graph
	 * and the showing graph to the argument, and creates the dontmove
	 * set.
	 * 
	 * @param g
	 */
	protected AbstractLayout(Graph graph) {
		this.graph = graph;
	}
	
	protected AbstractLayout(Graph graph, Transformer initializer) {
		this.graph = graph;
		this.locations = LazyMap.decorate(new HashMap(), initializer);
	}
	
	protected AbstractLayout(Graph graph, BoundingSphere size) {
		this.graph = graph;
		this.size = size;
	}
	
	protected AbstractLayout(Graph graph, Transformer initializer, BoundingSphere size) {
		this.graph = graph;
		this.locations = LazyMap.decorate(new HashMap(), initializer);
		this.size = size;
	}
    
    public void setGraph(Graph graph) {
        this.graph = graph;
        if(size != null && graph != null) {
        	initialize();
        }
    }
    
	/**
	 * When a visualization is resized, it presumably wants to fix the
	 * locations of the vertices and possibly to reinitialize its data. The
	 * current method calls initializeLocations followed by initialize_local.
	 * TODO: A better implementation wouldn't destroy the current information,
	 * but would either scale the current visualization, or move the nodes
	 * toward the new center.
	 */
	public void setSize(BoundingSphere size) {
		
		if(size != null && graph != null) {
			
			BoundingSphere oldSize = this.size;
			this.size = size;
			initialize();
			
			if(oldSize != null) {
				adjustLocations(oldSize, size);
			}
		}
	}
	
	private void adjustLocations(BoundingSphere oldSize, BoundingSphere size) {
		
		float oldWidth = 0;
		float oldHeight = 0;
		float oldDepth = 0;
		float width = 0;
		float height = 0;
		float depth = 0;
		
		oldWidth = oldHeight = oldDepth = (float) (2*oldSize.getRadius());
		width = height = depth = (float) (2*size.getRadius());

		float xOffset = (oldWidth - width) / 2;
		float yOffset = (oldHeight - height) / 2;
		float zOffset = (oldDepth - depth) / 2;

		// now, move each vertex to be at the new screen center
		while(true) {
		    try {
                for(V v : getGraph().getVertices()) {
		            offsetVertex(v, xOffset, yOffset, zOffset);
		        }
		        break;
		    } catch(ConcurrentModificationException cme) {
		    }
		}
	}
    
    public boolean isLocked(V v) {
        return dontmove.contains(v);
    }

    public Collection getVertices() {
    	return getGraph().getVertices();
    }
    
	/**
	 * Initializer, calls intialize_local and initializeLocations
	 * to start construction process.
	 */
	public abstract void initialize();

    public void setInitializer(Transformer initializer) {
    	this.locations = LazyMap.decorate(new HashMap(locations), initializer);
    }
    
	/**
	 * Returns the current size of the visualization space, accoring to the
	 * last call to resize().
	 * 
	 * @return the current size of the screen
	 */
	public BoundingSphere getSize() {
		return size;
	}

	/**
	 * Returns the Coordinates object that stores the vertex' x and y location.
	 * 
	 * @param v
	 *            A Vertex that is a part of the Graph being visualized.
	 * @return A Coordinates object with x and y locations.
	 */
	private Point3f getCoordinates(V v) {
        return locations.get(v);
	}
	
	public Point3f transform(V v) {
		return getCoordinates(v);
	}
	
	/**
	 * Returns the x coordinate of the vertex from the Coordinates object.
	 * in most cases you will be better off calling getLocation(Vertex v);
	 * @see edu.uci.ics.jung.visualization.layout.Layout#getX(edu.uci.ics.jung.graph.Vertex)
	 */
	public double getX(V v) {
        assert getCoordinates(v) != null : "Cannot getX for an unmapped vertex "+v;
        return getCoordinates(v).getX();
	}

	/**
	 * Returns the y coordinate of the vertex from the Coordinates object.
	 * In most cases you will be better off calling getLocation(Vertex v)
	 * @see edu.uci.ics.jung.visualization.layout.Layout#getX(edu.uci.ics.jung.graph.Vertex)
	 */
	public double getY(V v) {
        assert getCoordinates(v) != null : "Cannot getY for an unmapped vertex "+v;
        return getCoordinates(v).getY();
	}
	
    /**
     * @param v a Vertex of interest
     * @return the location point of the supplied vertex
     */
//	public Point3f getLocation(V v) {
//	    return getCoordinates(v);
//	}

	/**
	 * @param v
	 * @param xOffset
	 * @param yOffset
	 */
	protected void offsetVertex(V v, float xOffset, float yOffset, float zOffset) {
		Point3f c = getCoordinates(v);
        c.set(c.getX()+xOffset, c.getY()+yOffset, c.getZ()+zOffset);
		setLocation(v, c);
	}

	/**
	 * Accessor for the graph that represets all vertices.
	 * 
	 * @return the graph that contains all vertices.
	 */
	public Graph getGraph() {
	    return graph;
	}
	
	/**
	 * Forcibly moves a vertex to the (x,y) location by setting its x and y
	 * locations to the inputted location. Does not add the vertex to the
	 * "dontmove" list, and (in the default implementation) does not make any
	 * adjustments to the rest of the graph.
	 */
	public void setLocation(V picked, float x, float y, float z) {
		Point3f coord = getCoordinates(picked);
		coord.set(x, y, z);
	}

	public void setLocation(V picked, Point3f p) {
		Point3f coord = getCoordinates(picked);
		coord.set(p);
	}

	/**
	 * Adds the vertex to the DontMove list
	 */
	public void lock(V v, boolean state) {
		if(state == true) dontmove.add(v);
		else dontmove.remove(v);
	}
	
	public void lock(boolean lock) {
		for(V v : graph.getVertices()) {
			lock(v, lock);
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy