2 * Copyright (c) 2003, the JUNG Project and the Regents of the University of
3 * California All rights reserved.
5 * This software is open-source under the BSD license; see either "license.txt"
6 * or http://jung.sourceforge.net/license.txt for a description.
8 package edu.uci.ics.jung.algorithms.layout;
10 import java.awt.Dimension;
11 import java.awt.geom.Point2D;
12 import java.util.ConcurrentModificationException;
14 import org.apache.commons.collections15.Transformer;
16 import edu.uci.ics.jung.graph.Graph;
19 * The SpringLayout package represents a visualization of a set of nodes. The
20 * SpringLayout, which is initialized with a Graph, assigns X/Y locations to
21 * each node. When called <code>relax()</code>, the SpringLayout moves the
22 * visualization forward one step.
26 * @author Danyel Fisher
27 * @author Joshua O'Madadhain
29 public class SpringLayout2<V, E> extends SpringLayout<V,E>
31 protected int currentIteration;
32 protected int averageCounter;
33 protected int loopCountMax = 4;
34 protected boolean done;
36 protected Point2D averageDelta = new Point2D.Double();
39 * Constructor for a SpringLayout for a raw graph with associated
40 * dimension--the input knows how big the graph is. Defaults to the unit
43 @SuppressWarnings("unchecked")
44 public SpringLayout2(Graph<V,E> g) {
49 * Constructor for a SpringLayout for a raw graph with associated component.
51 * @param g the {@code Graph} to lay out
52 * @param length_function provides a length for each edge
54 public SpringLayout2(Graph<V,E> g, Transformer<E, Integer> length_function)
56 super(g, length_function);
60 * Relaxation step. Moves all nodes a smidge.
69 private void testAverageDeltas() {
70 double dx = this.averageDelta.getX();
71 double dy = this.averageDelta.getY();
72 if(Math.abs(dx) < .001 && Math.abs(dy) < .001) {
74 System.err.println("done, dx="+dx+", dy="+dy);
76 if(currentIteration > loopCountMax) {
77 this.averageDelta.setLocation(0,0);
84 protected void moveNodes() {
85 synchronized (getSize()) {
87 for (V v : getGraph().getVertices()) {
88 if (isLocked(v)) continue;
89 SpringVertexData vd = springVertexData.get(v);
90 if(vd == null) continue;
91 Point2D xyd = transform(v);
93 vd.dx += vd.repulsiondx + vd.edgedx;
94 vd.dy += vd.repulsiondy + vd.edgedy;
96 // int currentCount = currentIteration % this.loopCountMax;
97 // System.err.println(averageCounter+" --- vd.dx="+vd.dx+", vd.dy="+vd.dy);
98 // System.err.println("averageDelta was "+averageDelta);
100 averageDelta.setLocation(
101 ((averageDelta.getX() * averageCounter) + vd.dx) / (averageCounter+1),
102 ((averageDelta.getY() * averageCounter) + vd.dy) / (averageCounter+1)
104 // System.err.println("averageDelta now "+averageDelta);
105 // System.err.println();
108 // keeps nodes from moving any faster than 5 per time unit
109 xyd.setLocation(xyd.getX()+Math.max(-5, Math.min(5, vd.dx)),
110 xyd.getY()+Math.max(-5, Math.min(5, vd.dy)));
112 Dimension d = getSize();
114 int height = d.height;
116 if (xyd.getX() < 0) {
117 xyd.setLocation(0, xyd.getY());// setX(0);
118 } else if (xyd.getX() > width) {
119 xyd.setLocation(width, xyd.getY()); //setX(width);
121 if (xyd.getY() < 0) {
122 xyd.setLocation(xyd.getX(),0);//setY(0);
123 } else if (xyd.getY() > height) {
124 xyd.setLocation(xyd.getX(), height); //setY(height);
128 } catch(ConcurrentModificationException cme) {
135 public boolean done() {