Author: pwang
Date: 2010-09-22 16:10:25 -0700 (Wed, 22 Sep 2010)
New Revision: 22021

Added:
   
core3/layout-prefuse-impl/trunk/src/main/java/org/cytoscape/prefuse/layouts/internal/ForceDirectedLayoutTask.java
Log:
Refactored

Added: 
core3/layout-prefuse-impl/trunk/src/main/java/org/cytoscape/prefuse/layouts/internal/ForceDirectedLayoutTask.java
===================================================================
--- 
core3/layout-prefuse-impl/trunk/src/main/java/org/cytoscape/prefuse/layouts/internal/ForceDirectedLayoutTask.java
                           (rev 0)
+++ 
core3/layout-prefuse-impl/trunk/src/main/java/org/cytoscape/prefuse/layouts/internal/ForceDirectedLayoutTask.java
   2010-09-22 23:10:25 UTC (rev 22021)
@@ -0,0 +1,271 @@
+
+/*
+ Copyright (c) 2007, The Cytoscape Consortium (www.cytoscape.org)
+
+ The Cytoscape Consortium is:
+ - Institute for Systems Biology
+ - University of California San Diego
+ - Memorial Sloan-Kettering Cancer Center
+ - Institut Pasteur
+ - Agilent Technologies
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License, or
+ any later version.
+
+ This library is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  The software and
+ documentation provided hereunder is on an "as is" basis, and the
+ Institute for Systems Biology and the Whitehead Institute
+ have no obligations to provide maintenance, support,
+ updates, enhancements or modifications.  In no event shall the
+ Institute for Systems Biology and the Whitehead Institute
+ be liable to any party for direct, indirect, special,
+ incidental or consequential damages, including lost profits, arising
+ out of the use of this software and its documentation, even if the
+ Institute for Systems Biology and the Whitehead Institute
+ have been advised of the possibility of such damage.  See
+ the GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+*/
+
+package org.cytoscape.prefuse.layouts.internal; 
+
+import java.awt.Dimension;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.cytoscape.model.CyNode;
+import org.cytoscape.view.layout.AbstractGraphPartition;
+import org.cytoscape.view.layout.EdgeWeighter;
+import org.cytoscape.view.layout.LayoutEdge;
+import org.cytoscape.view.layout.LayoutNode;
+import org.cytoscape.view.layout.LayoutPartition;
+import org.cytoscape.view.model.CyNetworkView;
+import org.cytoscape.view.model.View;
+import org.cytoscape.work.Tunable;
+import org.cytoscape.work.undo.UndoSupport;
+
+import prefuse.util.force.DragForce;
+import prefuse.util.force.EulerIntegrator;
+import prefuse.util.force.ForceItem;
+import prefuse.util.force.ForceSimulator;
+import prefuse.util.force.Integrator;
+import prefuse.util.force.NBodyForce;
+import prefuse.util.force.RungeKuttaIntegrator;
+import prefuse.util.force.SpringForce;
+
+/**
+ * This class wraps the Prefuse force-directed layout algorithm.
+ * See {...@link http://prefuse.org} for more detail.
+ */
+public class ForceDirectedLayoutTask extends AbstractGraphPartition
+{
+       private ForceSimulator m_fsim;
+
+       public int numIterations;
+       public double defaultSpringCoefficient;
+       public double defaultSpringLength;
+       public double defaultNodeMass;
+       public ForceDirectedLayout.Integrators integrator;
+       //public ListSingleSelection<String> integratorChoice = "RUNGEKUTTA";
+       
+       
+       /**
+        * Value to set for doing unweighted layouts
+        */
+       public static final String UNWEIGHTEDATTRIBUTE = "(unweighted)";
+
+       private boolean supportWeights = true;
+       Map<LayoutNode,ForceItem> forceItems;
+
+       
+       /**
+        * Creates a new ForceDirectedLayout object.
+        */
+       public ForceDirectedLayoutTask(final CyNetworkView networkView, final 
String name,
+                                 final boolean selectedOnly, final 
Set<View<CyNode>> staticNodes,
+                                 final int numIterations, final double 
defaultSpringCoefficient, final double defaultSpringLength, 
+                                 final double defaultNodeMass, final 
ForceDirectedLayout.Integrators integrator)
+       {
+       
+               super(networkView, name, selectedOnly, staticNodes);
+               
+               this.numIterations = numIterations;
+               this.defaultSpringCoefficient = defaultSpringCoefficient;
+               this.defaultSpringLength = defaultSpringLength;
+               this.defaultNodeMass = defaultNodeMass;
+               this.integrator = integrator;
+               
+               if (edgeWeighter == null)
+                       edgeWeighter = new EdgeWeighter();
+
+               m_fsim = new ForceSimulator();
+               m_fsim.addForce(new NBodyForce());
+               m_fsim.addForce(new SpringForce());
+               m_fsim.addForce(new DragForce());
+
+               forceItems = new HashMap<LayoutNode,ForceItem>();
+
+       }
+       
+       public String getName() {
+               return "force-directed";
+       }
+
+       public String toString() {
+               return "Force-Directed Layout";
+       }
+
+       protected void initialize_local() {
+       }
+
+
+       public void layoutPartion(LayoutPartition part) {
+               Dimension initialLocation = null;
+               // System.out.println("layoutPartion: 
"+part.getEdgeList().size()+" edges");
+               // Calculate our edge weights
+               part.calculateEdgeWeights();
+               // System.out.println("layoutPartion: 
"+part.getEdgeList().size()+" edges after calculateEdgeWeights");
+
+               m_fsim.setIntegrator(integrator.getNewIntegrator());
+               m_fsim.clear();
+
+               // initialize nodes
+               for (LayoutNode ln: part.getNodeList()) {
+                       if ( !forceItems.containsKey(ln) )
+                               forceItems.put(ln, new ForceItem());
+                       ForceItem fitem = forceItems.get(ln); 
+                       fitem.mass = getMassValue(ln);
+                       fitem.location[0] = 0f; 
+                       fitem.location[1] = 0f; 
+                       m_fsim.addItem(fitem);
+               }
+               
+               // initialize edges
+               for (LayoutEdge e: part.getEdgeList()) {
+                       LayoutNode n1 = e.getSource();
+                       ForceItem f1 = forceItems.get(n1); 
+                       LayoutNode n2 = e.getTarget();
+                       ForceItem f2 = forceItems.get(n2); 
+                       if ( f1 == null || f2 == null )
+                               continue;
+                       // System.out.println("Adding edge "+e+" with spring 
coeffficient = "+getSpringCoefficient(e)+" and length "+getSpringLength(e));
+                       m_fsim.addSpring(f1, f2, getSpringCoefficient(e), 
getSpringLength(e)); 
+               }
+
+               // setTaskStatus(5); // This is a rough approximation, but 
probably good enough
+               if (taskMonitor != null) {
+                       taskMonitor.setStatusMessage("Initializing partition 
"+part.getPartitionNumber());
+               }
+
+               // Figure out our starting point
+               if (selectedOnly) {
+                       initialLocation = part.getAverageLocation();
+               }
+
+               // perform layout
+               long timestep = 1000L;
+               for ( int i = 0; i < numIterations && !cancelled; i++ ) {
+                       timestep *= (1.0 - i/(double)numIterations);
+                       long step = timestep+50;
+                       m_fsim.runSimulator(step);
+                       
setTaskStatus((int)(((double)i/(double)numIterations)*90.+5));
+               }
+               
+               // update positions
+               for (LayoutNode ln: part.getNodeList()) {
+                       if (!ln.isLocked()) {
+                               ForceItem fitem = forceItems.get(ln); 
+                               ln.setX(fitem.location[0]);
+                               ln.setY(fitem.location[1]);
+                               part.moveNodeToLocation(ln);
+                       }
+               }
+               // Not quite done, yet.  If we're only laying out selected 
nodes, we need
+               // to migrate the selected nodes back to their starting position
+               if (selectedOnly) {
+                       double xDelta = 0.0;
+                       double yDelta = 0.0;
+                       Dimension finalLocation = part.getAverageLocation();
+                       xDelta = finalLocation.getWidth() - 
initialLocation.getWidth();
+                       yDelta = finalLocation.getHeight() - 
initialLocation.getHeight();
+                       for (LayoutNode v: part.getNodeList()) {
+                               if (!v.isLocked()) {
+                                       v.decrement(xDelta, yDelta);
+                                       part.moveNodeToLocation(v);
+                               }
+                       }
+               }
+       }
+
+       /**
+        * Get the mass value associated with the given node. Subclasses should
+        * override this method to perform custom mass assignment.
+        * @param n the node for which to compute the mass value
+        * @return the mass value for the node. By default, all items are given
+        * a mass value of 1.0.
+        */
+       protected float getMassValue(LayoutNode n) {
+               return (float)defaultNodeMass;
+       }
+
+       /**
+        * Get the spring length for the given edge. Subclasses should
+        * override this method to perform custom spring length assignment.
+        * @param e the edge for which to compute the spring length
+        * @return the spring length for the edge. A return value of
+        * -1 means to ignore this method and use the global default.
+       */
+       protected float getSpringLength(LayoutEdge e) {
+               double weight = e.getWeight();
+               return (float)(defaultSpringLength/weight);
+       }
+
+       /**
+        * Get the spring coefficient for the given edge, which controls the
+        * tension or strength of the spring. Subclasses should
+        * override this method to perform custom spring tension assignment.
+        * @param e the edge for which to compute the spring coefficient.
+        * @return the spring coefficient for the edge. A return value of
+        * -1 means to ignore this method and use the global default.
+        */
+       protected float getSpringCoefficient(LayoutEdge e) {
+               return (float)defaultSpringCoefficient;
+       }
+
+       /**
+        * Return information about our algorithm
+        */
+       public boolean supportsSelectedOnly() {
+               return true;
+       }
+
+       public Set<Class<?>> supportsEdgeAttributes() {
+               Set<Class<?>> ret = new HashSet<Class<?>>();
+               if (!supportWeights)
+                       return ret;
+
+               ret.add( Integer.class );
+               ret.add( Double.class );
+
+               return ret;
+       }
+
+       public List getInitialAttributeList() {
+               ArrayList list = new ArrayList();
+               list.add(UNWEIGHTEDATTRIBUTE);
+
+               return list;
+       }
+
+}

-- 
You received this message because you are subscribed to the Google Groups 
"cytoscape-cvs" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/cytoscape-cvs?hl=en.

Reply via email to