/*
* TabularLayout.java
*
* Created on October 8, 2008, 2:32 PM
*
* Copyright 2003-2010 Tufts University Licensed under the
* Educational Community License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* http://www.osedu.org/licenses/ECL-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS"
* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
/**
*
* @author akumar03
*/
package edu.tufts.vue.layout;
import java.io.*;
import java.net.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import tufts.vue.*;
import edu.tufts.vue.metadata.MetadataList;
import edu.tufts.vue.metadata.VueMetadataElement;
import edu.tufts.vue.dataset.*;
/*
* This is similar to circular layout, except nodes that have more link
* gravitate to the center.
*/
public class ForceLayout extends Layout {
/** Creates a new instance of TabularLayout */
public ForceLayout() {
}
public LWMap createMap(Dataset ds,String mapName) throws Exception {
LWMap map = new LWMap(mapName);
return map;
}
public void layout(LWSelection selection) throws Exception {
Map<LWComponent,Integer> repeatMap = new HashMap<LWComponent,Integer>();
double minX =10000;
double minY = 10000;
int nodeSize = 100; // we assume node size is 100 which needs to be fixed.
boolean applyLayout = false;
int count = 0;
int total = 0;
int mod = 4;
int xAdd = 100;
int yAdd = 50;
Iterator<LWComponent> i = selection.iterator();
while (i.hasNext()) {
LWComponent c = i.next();
if (c.isManagedLocation())
continue;
if(c instanceof LWNode) {
LWNode node = (LWNode)c;
minX = node.getLocation().getX()<minX?node.getLocation().getX():minX;
minY =node.getLocation().getY()<minY?node.getLocation().getY():minY;
if(!repeatMap.containsKey(node)) repeatMap.put(node, new Integer(0));
total++;
}
}
// interate to map for links
i = VUE.getActiveMap().getAllDescendents(LWContainer.ChildKind.PROPER).iterator();
while (i.hasNext()) {
LWComponent c = i.next();
if (c.isManagedLocation())
continue;
if(c instanceof LWLink) {
applyLayout = true;
LWLink link = (LWLink)c;
LWComponent head= link.getHead();
LWComponent tail = link.getTail();
if(repeatMap.containsKey( head)) {
int nc= repeatMap.get( head).intValue();
repeatMap.put(head,new Integer(nc+1));
}
if(repeatMap.containsKey(tail)) {
int nc= repeatMap.get(tail).intValue();
repeatMap.put(tail,new Integer(nc+1));
}
}
}
if(applyLayout) {
double x = minX;
double y = minY;
double size = Math.sqrt(total)* nodeSize;
double radius = size/2;
double centerX = x+radius;
double centerY = y+radius;
i = selection.iterator();
while (i.hasNext()) {
LWComponent c = i.next();
if (c.isManagedLocation())
continue;
if(c instanceof LWNode) {
LWNode node = (LWNode)c;
double angle = Math.PI*2 * Math.random();
int nc= repeatMap.get(node).intValue();
double r = radius*Math.pow(1.00-(double)nc/total,2.00);
node.setLocation(centerX+r*Math.cos(angle),centerY+r*Math.sin(angle));
// System.out.println("Node: "+node.getLabel()+" r:"+r+" angle:"+angle+" nc:"+nc+" total:"+total+" radius:"+radius);
}
}
}
}
}