/* * 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 layout puts nodes in a circle. We may want to add the cellspacing and * also extend it to make an elipse */ public class FilledCircularLayout extends Layout { public static final double FACTOR =VueResources.getDouble("layout.space_ratio"); public static final int MAX_COLLISION_CHECK = VueResources.getInt("layout.check_overlap_number"); /** Creates a new instance of TabularLayout */ public FilledCircularLayout() { } public LWMap createMap(Dataset ds, String mapName) throws Exception { LWMap map = new LWMap(mapName); return map; } public void layout(LWSelection selection) throws Exception { double minX = Double.POSITIVE_INFINITY; double minY = Double.POSITIVE_INFINITY; double xAdd = X_COL_SIZE; // default horizontal distance between the nodes double yAdd = Y_COL_SIZE; //default vertical distance between nodes int total = 0; 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; xAdd = xAdd > node.getWidth() ? xAdd : node.getWidth(); yAdd = yAdd > node.getHeight() ? yAdd : node.getHeight(); total++; // System.out.println(node.getLabel()+"X= "+node.getLocation().getX()+" Y= "+node.getLocation().getY()+" MIN: "+minX+" : "+minY); } } xAdd = xAdd*1.10; // 10% gap xAdd = xAdd*1.10; double x = minX; double y = minY; double radius = Math.sqrt(FACTOR * total * xAdd * yAdd / Math.PI); double centerX = selection.getBounds().getCenterX(); double centerY = selection.getBounds().getCenterY(); 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(); double r = radius * (1 - Math.pow(Math.random(), 2.0)); x = centerX + r * Math.cos(angle); y = centerY + r * Math.sin(angle); boolean flag = true; int col_count = 0; while (flag && col_count < MAX_COLLISION_CHECK) { if ((VUE.getActiveViewer().pickNode((float) x, (float) y) != null) || (VUE.getActiveViewer().pickNode((float) x + node.getWidth(), (float) y + node.getHeight()) != null) || (VUE.getActiveViewer().pickNode((float) x , (float) y + node.getHeight()) != null ) || (VUE.getActiveViewer().pickNode((float) x + node.getWidth(), (float) y) != null)) { angle = Math.PI * 2 * Math.random(); r = radius * (1 - Math.pow(Math.random(), 2.0)); x = centerX + r * Math.cos(angle)-node.getWidth(); y = centerY + r * Math.sin(angle)-node.getHeight(); } else { flag = false; } col_count++; // System.out.println("count: "+col_count+" MAX"+MAX_COLLISION_CHECK+" node: "+node.getLabel()); } node.setLocation(x, y); } } } }