package prefuse.action.layout; import java.awt.geom.Rectangle2D; import java.util.Iterator; import prefuse.data.tuple.TupleSet; import prefuse.visual.VisualItem; /** * Layout action that positions visual items along a circle. By default, * items are sorted in the order in which they iterated over. * * @author <a href="http://jheer.org">jeffrey heer</a> */ public class CircleLayout extends Layout { private double m_radius; // radius of the circle layout /** * Create a CircleLayout; the radius of the circle layout will be computed * automatically based on the display size. * @param group the data group to layout */ public CircleLayout(String group) { super(group); } /** * Create a CircleLayout; use the specified radius for the the circle layout, * regardless of the display size. * @param group the data group to layout * @param radius the radius of the circle layout. */ public CircleLayout(String group, double radius) { super(group); m_radius = radius; } /** * Return the radius of the layout circle. * @return the circle radius */ public double getRadius() { return m_radius; } /** * Set the radius of the layout circle. * @param radius the circle radius to use */ public void setRadius(double radius) { m_radius = radius; } /** * @see prefuse.action.Action#run(double) */ public void run(double frac) { TupleSet ts = m_vis.getGroup(m_group); int nn = ts.getTupleCount(); Rectangle2D r = getLayoutBounds(); double height = r.getHeight(); double width = r.getWidth(); double cx = r.getCenterX(); double cy = r.getCenterY(); double radius = m_radius; if (radius <= 0) { radius = 0.45 * (height < width ? height : width); } Iterator items = ts.tuples(); for (int i=0; items.hasNext(); i++) { VisualItem n = (VisualItem)items.next(); double angle = (2*Math.PI*i) / nn; double x = Math.cos(angle)*radius + cx; double y = Math.sin(angle)*radius + cy; setX(n, null, x); setY(n, null, y); } } } // end of class CircleLayout