Author: paperwing
Date: 2012-03-23 14:35:32 -0700 (Fri, 23 Mar 2012)
New Revision: 28634

Modified:
   
csplugins/trunk/toronto/yuedong/paperwing-impl/src/main/java/org/cytoscape/paperwing/internal/geometric/Vector3.java
   
csplugins/trunk/toronto/yuedong/paperwing-impl/src/main/java/org/cytoscape/paperwing/internal/layouts/SphericalLayoutAlgorithmTask.java
Log:
Completed algorithm for distributing partitions of a graph in an evenly-spaced 
3-dimensional cube with length proportional to the radius of the largest 
partition. Sample: 
http://wiki.cytoscape.org/Cytoscape_3/3D_Renderer?action=AttachFile&do=view&target=screenshot-0.58-spherical2.png

Modified: 
csplugins/trunk/toronto/yuedong/paperwing-impl/src/main/java/org/cytoscape/paperwing/internal/geometric/Vector3.java
===================================================================
--- 
csplugins/trunk/toronto/yuedong/paperwing-impl/src/main/java/org/cytoscape/paperwing/internal/geometric/Vector3.java
        2012-03-23 20:10:50 UTC (rev 28633)
+++ 
csplugins/trunk/toronto/yuedong/paperwing-impl/src/main/java/org/cytoscape/paperwing/internal/geometric/Vector3.java
        2012-03-23 21:35:32 UTC (rev 28634)
@@ -140,6 +140,18 @@
                return new Vector3(x - other.x, y - other.y, z - other.z);
        }
        
+       /** Subtract the specified values from the coordinates of this vector
+        * 
+        * @param x X-coordinate
+        * @param y Y-coordinate
+        * @param z Z-coordinate
+        */
+       public void subtractLocal(double x, double y, double z) {
+               this.x -= x;
+               this.y -= y;
+               this.z -= z;
+       }
+       
        /** Find the angle (<180 degrees) between this vector and another vector
         * 
         * @param other The other vector used to find the angle 

Modified: 
csplugins/trunk/toronto/yuedong/paperwing-impl/src/main/java/org/cytoscape/paperwing/internal/layouts/SphericalLayoutAlgorithmTask.java
===================================================================
--- 
csplugins/trunk/toronto/yuedong/paperwing-impl/src/main/java/org/cytoscape/paperwing/internal/layouts/SphericalLayoutAlgorithmTask.java
     2012-03-23 20:10:50 UTC (rev 28633)
+++ 
csplugins/trunk/toronto/yuedong/paperwing-impl/src/main/java/org/cytoscape/paperwing/internal/layouts/SphericalLayoutAlgorithmTask.java
     2012-03-23 21:35:32 UTC (rev 28634)
@@ -37,52 +37,99 @@
        protected void doLayout(TaskMonitor taskMonitor) {
                
                // Break graph into partitions
-               List<LayoutPartition> partitions = 
PartitionUtil.partition(networkView, false, null);
-               int numPartitions = partitions.size();
-               int count = 0;
+               List<LayoutPartition> layoutPartitions = 
PartitionUtil.partition(networkView, false, null);
+               int numPartitions = layoutPartitions.size();
                
                System.out.println("Number of partitions: " + numPartitions);
                
-               double xOffsetAmount = 0;
-               double yOffsetAmount = 0;
-               double largestRadius = -1;
+               Collection<Collection<View<CyNode>>> partitions = new 
HashSet<Collection<View<CyNode>>>(layoutPartitions.size());
                
                Collection<View<CyNode>> partitionNodeViews;
                
-               Map<LayoutPartition, Double> partitionRadii = new 
HashMap<LayoutPartition, Double>();
-               
-               for (LayoutPartition partition : partitions) {
+               for (LayoutPartition partition : layoutPartitions) {
                        partitionNodeViews = new HashSet<View<CyNode>>();
                        
                        for (LayoutNode layoutNode : partition.getNodeList()) {
                                View<CyNode> nodeView = 
layoutNode.getNodeView();
-                               
-                               
nodeView.setVisualProperty(BasicVisualLexicon.NODE_X_LOCATION, 
-                                               
nodeView.getVisualProperty(BasicVisualLexicon.NODE_X_LOCATION) + xOffsetAmount);
-                               
-                               
nodeView.setVisualProperty(BasicVisualLexicon.NODE_Y_LOCATION, 
-                                               
nodeView.getVisualProperty(BasicVisualLexicon.NODE_Y_LOCATION) + yOffsetAmount);
-                               
-                               
                                partitionNodeViews.add(nodeView);
                        }
-                       arrangeAsSphere(partitionNodeViews);
                        
-                       double subgraphRadius = 
findSubgraphRadius(partitionNodeViews);
-                       partitionRadii.put(partition, subgraphRadius);
+                       partitions.add(partitionNodeViews);
+               }
+               
+               for (Collection<View<CyNode>> partition : partitions) {
+                       arrangeAsSphere(partition);
+               }
+               
+               arrangePartitions(partitions);
+       }
+       
+       private void arrangePartitions(Collection<Collection<View<CyNode>>> 
partitions) {
+               // Consider sorting partitions in order of decreasing radius?
+               
+               Map<Collection<View<CyNode>>, Double> partitionRadii = new 
HashMap<Collection<View<CyNode>>, Double>(partitions.size());
+               
+               // Basic approach: 1 partition per cube
+               int cubeLength = (int) Math.ceil(Math.pow(partitions.size(), 
1.0/3));
+               
+               // System.out.println("cubeLength: " + cubeLength);
+               
+               // Average position of all nodes
+               Vector3 averageTotalNodePosition = new Vector3();
+               int totalNodeCount = 0;
+               
+               double largestRadius = -1;
+               
+               for (Collection<View<CyNode>> partition : partitions) {
+                       
averageTotalNodePosition.addLocal(findCenter(partition).multiply(partition.size()));
+                       totalNodeCount += partition.size();
                        
-                       xOffsetAmount += subgraphRadius + 50;
+                       double partitionRadius = findSubgraphRadius(partition);
+                       partitionRadii.put(partition, partitionRadius);
                        
-                       if (subgraphRadius > largestRadius) {
-                               largestRadius = subgraphRadius;
+                       if (partitionRadius > largestRadius) {
+                               largestRadius = partitionRadius;
                        }
+               }
+               
+               largestRadius = Math.max(largestRadius, 50);
+               largestRadius *= 2;
+               
+               // Calculate the average position of all nodes by using the 
average position of partitions weighted by their node count
+               averageTotalNodePosition.divideLocal(totalNodeCount);
+               
+               int count = 0;
+               for (Collection<View<CyNode>> partition : partitions) {
+                       int x = count % cubeLength;
+                       int y = count / cubeLength % cubeLength;
+                       int z = count / cubeLength / cubeLength;
                        
+                       // TODO: Need to set offset so that total average node 
position is preserved
+                       Vector3 offset = new Vector3(x * largestRadius, y * 
largestRadius, z * largestRadius);
+                       double halfCubeActualLength = (double) (cubeLength - 1) 
/ 2 * largestRadius;
+                       offset.subtractLocal(halfCubeActualLength, 
halfCubeActualLength, halfCubeActualLength);
+                       
+                       displaceNodes(partition, 
offset.plus(averageTotalNodePosition));
+                       
+                       // System.out.println(new Vector3(x, y, z));
                        count++;
                }
-               
+       }
        
-               // arrangeAsSphere(networkView.getNodeViews());
+       // Displace a set of nodes such that their average of position is moved 
to the given point.
+       // Each node's position relative to the average position should remain 
unchanged.
+       private void displaceNodes(Collection<View<CyNode>> nodeViews, Vector3 
target) {
+               Vector3 currentCenter = findCenter(nodeViews);
+               Vector3 displacement = target.subtract(currentCenter);
                
+               for (View<CyNode> nodeView : nodeViews) {
+                       
nodeView.setVisualProperty(BasicVisualLexicon.NODE_X_LOCATION,
+                                       
nodeView.getVisualProperty(BasicVisualLexicon.NODE_X_LOCATION) + 
displacement.x());
+                       
nodeView.setVisualProperty(BasicVisualLexicon.NODE_Y_LOCATION,
+                                       
nodeView.getVisualProperty(BasicVisualLexicon.NODE_Y_LOCATION) + 
displacement.y());
+                       
nodeView.setVisualProperty(BasicVisualLexicon.NODE_Z_LOCATION,
+                                       
nodeView.getVisualProperty(BasicVisualLexicon.NODE_Z_LOCATION) + 
displacement.z());
+               }
        }
        
        private void arrangeAsBox(Collection<View<CyNode>> nodeViews) {

-- 
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