package uk.ac.rhul.cs.graph; import java.awt.geom.AffineTransform; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.util.Arrays; /** * Class representing a layout of a graph * * @author tamas */ public class Layout { /** Internal array of coordinates */ public double[] coordinates = null; /** * Creates an empty layout for the given graph */ public Layout(Graph graph) { this(graph.getNodeCount()); } /** * Creates an empty layout for the given number of nodes */ public Layout(int numberOfNodes) { coordinates = new double[2 * numberOfNodes]; Arrays.fill(coordinates, 0); } /** * Fits the layout into the given rectangle by rescaling and translating coordinates appropriately * * @param rectangle the rectangle in which we want to fit the layout */ public void fitToRectangle(Rectangle2D rectangle) { Rectangle2D currentBoundingRectangle = this.getBoundingRectangle(); double sx = rectangle.getWidth() / currentBoundingRectangle.getWidth(); double sy = rectangle.getHeight() / currentBoundingRectangle.getHeight(); /* First, translate the current rectangle so that the lower left corner is in * the origin */ AffineTransform trans = AffineTransform.getTranslateInstance( -currentBoundingRectangle.getMinX() * sx, -currentBoundingRectangle.getMinY() * sy ); /* Next, scale it up for the desired size */ trans.scale(sx, sy); /* Finally, translate the lower left corner to where it should be */ trans.translate(rectangle.getMinX() / sx, rectangle.getMinY() / sy); /* Now, apply the transformation to all the coordinates */ trans.transform(coordinates, 0, coordinates, 0, coordinates.length / 2); } /** * Returns the bounding rectangle of the layout */ public Rectangle2D getBoundingRectangle() { if (coordinates.length == 0) return null; double minX = coordinates[0], minY = coordinates[1]; double maxX = coordinates[0], maxY = coordinates[1]; int i, n = coordinates.length; for (i = 2; i < n; i += 2) { double x = coordinates[i], y = coordinates[i+1]; if (minX > x) minX = x; if (minY > y) minY = y; if (maxX < x) maxX = x; if (maxY < y) maxY = y; } return new Rectangle2D.Double(minX, minY, maxX-minX, maxY-minY); } /** * Sets the coordinates of the node with the given index * * @param i the index of the node * @param x the X coordinate * @param y the Y coordinate */ public void setCoordinates(int i, double x, double y) { coordinates[i*2] = x; coordinates[i*2+1] = y; } /** * Returns the number of points in this layout */ public int size() { return this.coordinates.length / 2; } /** * Returns the coordinates of the given point in this layout * * @param i the index of the node */ public Point2D getCoordinates(int i) { return new Point2D.Double(coordinates[i*2], coordinates[i*2+1]); } }