View Javadoc

1   /*
2    * Copyright (c) 2003, the JUNG Project and the Regents of the University of
3    * California All rights reserved.
4    * 
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.
7    */
8   package edu.uci.ics.jung.algorithms.layout;
9   
10  import java.awt.Dimension;
11  import java.awt.geom.Point2D;
12  import java.util.ConcurrentModificationException;
13  
14  import org.apache.commons.collections15.Transformer;
15  
16  import edu.uci.ics.jung.graph.Graph;
17  
18  /**
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.
23   * 
24   * 
25   * 
26   * @author Danyel Fisher
27   * @author Joshua O'Madadhain
28   */
29  public class SpringLayout2<V, E> extends SpringLayout<V,E> 
30  {
31      protected int currentIteration;
32      protected int averageCounter;
33      protected int loopCountMax = 4;
34      protected boolean done;
35      
36      protected Point2D averageDelta = new Point2D.Double();
37      
38      /**
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
41       * length function.
42       */
43      @SuppressWarnings("unchecked")
44      public SpringLayout2(Graph<V,E> g) {
45          super(g);
46      }
47  
48      /**
49       * Constructor for a SpringLayout for a raw graph with associated component.
50       *
51       * @param g the {@code Graph} to lay out
52       * @param length_function provides a length for each edge
53       */
54      public SpringLayout2(Graph<V,E> g, Transformer<E, Integer> length_function)
55      {
56          super(g, length_function);
57      }
58  
59      /**
60       * Relaxation step. Moves all nodes a smidge.
61       */
62      @Override
63      public void step() {
64          super.step();
65      	currentIteration++;
66      	testAverageDeltas();
67      }
68      
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) {
73      		done = true;
74      		System.err.println("done, dx="+dx+", dy="+dy);
75      	}
76          if(currentIteration > loopCountMax) {
77          	this.averageDelta.setLocation(0,0);
78          	averageCounter = 0;
79          	currentIteration = 0;
80          }
81      }
82  
83      @Override
84      protected void moveNodes() {
85          synchronized (getSize()) {
86              try {
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);
92                      
93                      vd.dx += vd.repulsiondx + vd.edgedx;
94                      vd.dy += vd.repulsiondy + vd.edgedy;
95                      
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);
99  
100                     averageDelta.setLocation(
101                     		((averageDelta.getX() * averageCounter) + vd.dx) / (averageCounter+1),
102                     		((averageDelta.getY() * averageCounter) + vd.dy) / (averageCounter+1)
103                     		);
104 //                    System.err.println("averageDelta now "+averageDelta);
105 //                    System.err.println();
106                     averageCounter++;
107                     
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)));
111                     
112                     Dimension d = getSize();
113                     int width = d.width;
114                     int height = d.height;
115                     
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);
120                     }
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);
125                     }
126                     
127                 }
128             } catch(ConcurrentModificationException cme) {
129                 moveNodes();
130             }
131         }
132     }
133 
134     @Override
135     public boolean done() {
136         return done;
137     }
138 
139 }