
edu.uci.ics.jung.algorithms.layout.BalloonLayout Maven / Gradle / Ivy
/*
* Copyright (c) 2005, 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 9, 2005
*/
package edu.uci.ics.jung.algorithms.layout;
import java.awt.Dimension;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.collections15.Transformer;
import org.apache.commons.collections15.map.LazyMap;
import edu.uci.ics.jung.graph.Forest;
import edu.uci.ics.jung.graph.util.TreeUtils;
/**
* A {@code Layout} implementation that assigns positions to {@code Tree} or
* {@code Forest} vertices using associations with nested circles ("balloons").
* A balloon is nested inside another balloon if the first balloon's subtree
* is a subtree of the second balloon's subtree.
*
* @author Tom Nelson
*
*/
public class BalloonLayout extends TreeLayout {
protected Map polarLocations =
LazyMap.decorate(new HashMap(),
new Transformer() {
public PolarPoint transform(V arg0) {
return new PolarPoint();
}});
protected Map radii = new HashMap();
/**
* Creates an instance based on the input forest.
*/
public BalloonLayout(Forest g)
{
super(g);
}
protected void setRootPolars()
{
List roots = TreeUtils.getRoots(graph);
if(roots.size() == 1) {
// its a Tree
V root = roots.get(0);
setRootPolar(root);
setPolars(new ArrayList(graph.getChildren(root)),
getCenter(), getSize().width/2);
} else if (roots.size() > 1) {
// its a Forest
setPolars(roots, getCenter(), getSize().width/2);
}
}
protected void setRootPolar(V root) {
PolarPoint pp = new PolarPoint(0,0);
Point2D p = getCenter();
polarLocations.put(root, pp);
locations.put(root, p);
}
protected void setPolars(List kids, Point2D parentLocation, double parentRadius) {
int childCount = kids.size();
if(childCount == 0) return;
// handle the 1-child case with 0 limit on angle.
double angle = Math.max(0, Math.PI / 2 * (1 - 2.0/childCount));
double childRadius = parentRadius*Math.cos(angle) / (1 + Math.cos(angle));
double radius = parentRadius - childRadius;
double rand = Math.random();
for(int i=0; i< childCount; i++) {
V child = kids.get(i);
double theta = i* 2*Math.PI/childCount + rand;
radii.put(child, childRadius);
PolarPoint pp = new PolarPoint(theta, radius);
polarLocations.put(child, pp);
Point2D p = PolarPoint.polarToCartesian(pp);
p.setLocation(p.getX()+parentLocation.getX(), p.getY()+parentLocation.getY());
locations.put(child, p);
setPolars(new ArrayList(graph.getChildren(child)), p, childRadius);
}
}
@Override
public void setSize(Dimension size) {
this.size = size;
setRootPolars();
}
/**
* Returns the coordinates of {@code v}'s parent, or the
* center of this layout's area if it's a root.
*/
public Point2D getCenter(V v) {
V parent = graph.getParent(v);
if(parent == null) {
return getCenter();
}
return locations.get(parent);
}
@Override
public void setLocation(V v, Point2D location) {
Point2D c = getCenter(v);
Point2D pv = new Point2D.Double(location.getX()-c.getX(),location.getY()-c.getY());
PolarPoint newLocation = PolarPoint.cartesianToPolar(pv);
polarLocations.get(v).setLocation(newLocation);
Point2D center = getCenter(v);
pv.setLocation(pv.getX()+center.getX(), pv.getY()+center.getY());
locations.put(v, pv);
}
@Override
public Point2D transform(V v) {
return locations.get(v);
}
/**
* @return the radii
*/
public Map getRadii() {
return radii;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy