/*
* ClusterLayout.java
*
* Created on October 1, 2008, 2:14 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 java.awt.geom.Point2D;
import javax.swing.*;
import tufts.vue.*;
import edu.tufts.vue.metadata.MetadataList;
import edu.tufts.vue.metadata.VueMetadataElement;
import edu.tufts.vue.dataset.*;
public class Cluster2Layout extends Layout {
public static String DEFAULT_METADATA_LABEL = "default";
public static final int MINX_RADIUS = VueResources
.getInt("layout.minx_radius");
public static final int MINY_RADIUS = VueResources
.getInt("layout.miny_radius");
public static final int X_SPACING = VueResources.getInt("layout.x_spacing");
public static final int Y_SPACING = VueResources.getInt("layout.y_spacing");
public static final double FACTOR = 2.5;
public static final int MAX_COLLISION_CHECK = VueResources
.getInt("layout.check_overlap_number");
/** Creates a new instance of ClusterLayout */
public Cluster2Layout() {
}
public LWMap createMap(Dataset ds, String mapName) throws Exception {
LWMap map = new LWMap(mapName);
return map;
}
public void layout(LWSelection selection) {
HashMap<LWComponent, ArrayList<LWComponent>> clusterMap = new HashMap<LWComponent, ArrayList<LWComponent>>();
double minX = Double.POSITIVE_INFINITY;
double minY = Double.POSITIVE_INFINITY;
double maxNodeWidth = X_COL_SIZE;
double maxNodeHeight = Y_COL_SIZE;
double centerX = selection.getBounds().getCenterX();
double centerY = selection.getBounds().getCenterY();
double maxDistance = 0;
// compute the radius of the cluster
double area = 0;
for (LWComponent component : selection) {
if (component instanceof LWNode) {
LWNode node = (LWNode) component;
area += node.getWidth() * node.getHeight();
double distance = Point2D.distance(centerX, centerY, node
.getX(), node.getY());
if (distance > maxDistance)
maxDistance = distance;
}
}
double radius = Math.sqrt((area * FACTOR / Math.PI));
// move nodes in selection
Iterator<LWComponent> i = VUE.getActiveMap().getAllDescendents(
LWContainer.ChildKind.PROPER).iterator();
while (i.hasNext()) {
LWComponent c = i.next();
if (c.isManagedLocation())
continue;
if (c instanceof LWNode) {
LWNode node = (LWNode) c;
double x = node.getX();
double y = node.getY();
double angle = Math.atan2(centerY - y, x - centerX);
double dist = Point2D.distance(centerX, centerY, x, y);
if (selection.contains(node)) {
double newDist = radius * dist / maxDistance;
double newX = centerX + newDist * Math.cos(angle);
double newY = centerY - newDist * Math.sin(angle);
node.setLocation(newX, newY);
} else {
double shiftRange = 3 * radius;
// System.out.println(node.getLabel()+"\t"+radius+"\t"+shiftRange);
if (dist < shiftRange) {
double newDist = dist +(shiftRange - dist) * radius
/ shiftRange;
double newX = centerX + newDist * Math.cos(angle);
double newY = centerY - newDist * Math.sin(angle);
node.setLocation(newX, newY);
}
}
}
}
}
}