/* * StretchLayout.java * * Created on November 24, 2008, 12:21 PM * * To change this template, choose Tools | Template Manager * and open the template in the editor. */ /** * * @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.dataset.*; import java.awt.geom.Rectangle2D; import java.awt.geom.Point2D; import java.awt.geom.Line2D; public class StretchLayout extends Layout { /** Creates a new instance of StretchLayout */ public StretchLayout() { } public void layout(LWSelection selection) { // compute the bounding rectangle of selection int X_PADDING = 40; // applied only on top and left int Y_PADDING = 20; int MAX_X_MOVE =80; int MAX_Y_MOVE = 40; double MAX_SHIFT = 1.2; double SHIFT_RANGE = 1.5; double EXPAND = 1.25; // expands the ellipse by a factor of 1.1 Rectangle2D boundingRect = selection.getBounds(); double maxX = boundingRect.getMaxX(); double maxY = boundingRect.getMaxY(); double minX = boundingRect.getMinX(); double minY = boundingRect.getMinY(); final double centerX = boundingRect.getCenterX(); final double centerY = boundingRect.getCenterY(); double xRange = Math.abs(maxX-minX)/2; double yRange = Math.abs(maxY-minY)/2; // determine the axis a & b of the ellipse that bounds the rectangle double angleTopLeft = Math.atan((centerY-minY)/(centerX-minX)); double a = xRange; double b = yRange; double ptEllipseX = centerX - a*Math.cos(angleTopLeft); double ptEllipseY = centerY - b*Math.sin(angleTopLeft); double distPt = Point2D.distance(ptEllipseX,ptEllipseY,centerX,centerY); double distTopLeft = Point2D.distance(minX,minY,centerX,centerY); double ratio = distTopLeft/distPt; double outerA = a*ratio*EXPAND; double outerB = b*ratio*EXPAND; // System.out.println("ELLIPSE: a:"+a+" b: "+b+" xRrange:" + xRange+" yRange:"+yRange+" ratio:"+ratio); // System.out.printf("center: %.2f,%.2f\n",centerX,centerY); // move all nodes around the selection Iterator<LWComponent> i = VUE.getActiveMap().getAllDescendents(LWContainer.ChildKind.PROPER).iterator(); while (i.hasNext()) { LWComponent c = i.next(); if (c.isManagedLocation()) continue; if(!selection.contains(c) && c instanceof LWNode) { // if node is within the selection move it to the bounding box Point2D location = c.getLocation(); double newX = location.getX(); double newY = location.getY(); double y = location.getY(); double x =location.getX(); double angle = Math.atan2(centerY-y,x-centerX); if(boundingRect.contains(location)) { newX = centerX-X_PADDING+outerA*Math.cos(angle); newY = centerY-Y_PADDING-outerB*Math.sin(angle); // System.out.println("Setting new location for: "+c.getLabel()+" angle:"+Math.toDegrees(angle)); // System.out.printf("x:%3.2f,y:%3.2f,newX:%3.2f,newY:%3.2f\n",x,y,newX,newY); } else { double xInnerEllipse = centerX+a*Math.cos(angle); double yInnerEllipse = centerY-b*Math.sin(angle); double xOuterEllipse = centerX+outerA*Math.cos(angle); double yOuterEllipse = centerY-outerB*Math.sin(angle); double distInner = Point2D.distance(centerX,centerY,xInnerEllipse,yInnerEllipse); double distOuter = Point2D.distance(centerX,centerY,xOuterEllipse,yOuterEllipse); double distPoint = Point2D.distance(centerX,centerY,x,y); if(distPoint < SHIFT_RANGE*distOuter) { double factor = MAX_SHIFT+ (distPoint-distInner)*(SHIFT_RANGE-MAX_SHIFT)/(SHIFT_RANGE*distOuter-distInner); double newA = outerA*factor; double newB = outerB*factor; newX = centerX-X_PADDING+newA*Math.cos(angle); newY = centerY-Y_PADDING-newB*Math.sin(angle); } } c.setLocation(newX,newY); } } } public LWMap createMap(Dataset ds,String mapName) throws Exception { LWMap map = new LWMap(mapName); return map; } }