X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=src%2Fcom%2Finfomatiq%2Fjsi%2FRectangle.java;fp=src%2Fcom%2Finfomatiq%2Fjsi%2FRectangle.java;h=737e6cf7847038d4a5dc8fc181291d37c6038fe9;hb=0f9ce20a060db6537a47b549cbf24fd268699ac6;hp=0000000000000000000000000000000000000000;hpb=57376a862c00fa1c8731f9989085fcfceeee0370;p=anneal.git diff --git a/src/com/infomatiq/jsi/Rectangle.java b/src/com/infomatiq/jsi/Rectangle.java new file mode 100644 index 0000000..737e6cf --- /dev/null +++ b/src/com/infomatiq/jsi/Rectangle.java @@ -0,0 +1,366 @@ +// Rectangle.java +// Java Spatial Index Library +// Copyright (C) 2002 Infomatiq Limited +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package com.infomatiq.jsi; + +import java.util.Arrays; + +/** + * Currently hardcoded to 2 dimensions, but could be extended. + * + * @author aled.morris@infomatiq.co.uk + * @version 1.0b2 + */ +public class Rectangle { + /** + * Number of dimensions in a rectangle. In theory this + * could be exended to three or more dimensions. + */ + public final static int DIMENSIONS = 3; + + /** + * array containing the minimum value for each dimension; ie { min(x), min(y) } + */ + public float[] max; + + /** + * array containing the maximum value for each dimension; ie { max(x), max(y) } + */ + public float[] min; + + /** + * Constructor. + * + * @param x1 coordinate of any corner of the rectangle + * @param y1 (see x1) + * @param x2 coordinate of the opposite corner + * @param y2 (see x2) + */ + public Rectangle(float x1, float y1, float z1, float x2, float y2, float z2) { + min = new float[DIMENSIONS]; + max = new float[DIMENSIONS]; + set(x1, y1, z1, x2, y2, z2); + } + + /** + * Constructor. + * + * @param min array containing the minimum value for each dimension; ie { min(x), min(y) } + * @param max array containing the maximum value for each dimension; ie { max(x), max(y) } + */ + public Rectangle(float[] min, float[] max) { + if (min.length != DIMENSIONS || max.length != DIMENSIONS) { + throw new RuntimeException("Error in Rectangle constructor: " + + "min and max arrays must be of length " + DIMENSIONS); + } + + this.min = new float[DIMENSIONS]; + this.max = new float[DIMENSIONS]; + + set(min, max); + } + + /** + * Sets the size of the rectangle. + * + * @param x1 coordinate of any corner of the rectangle + * @param y1 (see x1) + * @param x2 coordinate of the opposite corner + * @param y2 (see x2) + */ + public void set(float x1, float y1, float z1, float x2, float y2, float z2) { + min[0] = Math.min(x1, x2); + min[1] = Math.min(y1, y2); + min[2] = Math.min(z1, z2); + max[0] = Math.max(x1, x2); + max[1] = Math.max(y1, y2); + max[2] = Math.max(z1, z2); + } + + /** + * Sets the size of the rectangle. + * + * @param min array containing the minimum value for each dimension; ie { min(x), min(y) } + * @param max array containing the maximum value for each dimension; ie { max(x), max(y) } + */ + public void set(float[] min, float[] max) { + System.arraycopy(min, 0, this.min, 0, DIMENSIONS); + System.arraycopy(max, 0, this.max, 0, DIMENSIONS); + } + + /** + * Make a copy of this rectangle + * + * @return copy of this rectangle + */ + public Rectangle copy() { + return new Rectangle(min, max); + } + + /** + * Determine whether an edge of this rectangle overlies the equivalent + * edge of the passed rectangle + */ + public boolean edgeOverlaps(Rectangle r) { + for (int i = 0; i < DIMENSIONS; i++) { + if (min[i] == r.min[i] || max[i] == r.max[i]) { + return true; + } + } + return false; + } + + /** + * Determine whether this rectangle intersects the passed rectangle + * + * @param r The rectangle that might intersect this rectangle + * + * @return true if the rectangles intersect, false if they do not intersect + */ + public boolean intersects(Rectangle r) { + // Every dimension must intersect. If any dimension + // does not intersect, return false immediately. + for (int i = 0; i < DIMENSIONS; i++) { + if (max[i] < r.min[i] || min[i] > r.max[i]) { + return false; + } + } + return true; + } + + /** + * Determine whether this rectangle contains the passed rectangle + * + * @param r The rectangle that might be contained by this rectangle + * + * @return true if this rectangle contains the passed rectangle, false if + * it does not + */ + public boolean contains(Rectangle r) { + for (int i = 0; i < DIMENSIONS; i++) { + if (max[i] < r.max[i] || min[i] > r.min[i]) { + return false; + } + } + return true; + } + + /** + * Determine whether this rectangle is contained by the passed rectangle + * + * @param r The rectangle that might contain this rectangle + * + * @return true if the passed rectangle contains this rectangle, false if + * it does not + */ + public boolean containedBy(Rectangle r) { + for (int i = 0; i < DIMENSIONS; i++) { + if (max[i] > r.max[i] || min[i] < r.min[i]) { + return false; + } + } + return true; + } + + /** + * Return the distance between this rectangle and the passed point. + * If the rectangle contains the point, the distance is zero. + * + * @param p Point to find the distance to + * + * @return distance beween this rectangle and the passed point. + */ + public float distance(Point p) { + float distanceSquared = 0; + for (int i = 0; i < DIMENSIONS; i++) { + float greatestMin = Math.max(min[i], p.coordinates[i]); + float leastMax = Math.min(max[i], p.coordinates[i]); + if (greatestMin > leastMax) { + distanceSquared += ((greatestMin - leastMax) * (greatestMin - leastMax)); + } + } + return (float) Math.sqrt(distanceSquared); + } + + /** + * Return the distance between this rectangle and the passed rectangle. + * If the rectangles overlap, the distance is zero. + * + * @param r Rectangle to find the distance to + * + * @return distance between this rectangle and the passed rectangle + */ + + public float distance(Rectangle r) { + float distanceSquared = 0; + for (int i = 0; i < DIMENSIONS; i++) { + float greatestMin = Math.max(min[i], r.min[i]); + float leastMax = Math.min(max[i], r.max[i]); + if (greatestMin > leastMax) { + distanceSquared += ((greatestMin - leastMax) * (greatestMin - leastMax)); + } + } + return (float) Math.sqrt(distanceSquared); + } + + /** + * Return the squared distance from this rectangle to the passed point + */ + private float distanceSquared(int dimension, float point) { + float distanceSquared = 0; + float tempDistance = point - max[dimension]; + for (int i = 0; i < 2; i++) { + if (tempDistance > 0) { + distanceSquared = (tempDistance * tempDistance); + break; + } + tempDistance = min[dimension] - point; + } + return distanceSquared; + } + + /** + * Return the furthst possible distance between this rectangle and + * the passed rectangle. + * + * Find the distance between this rectangle and each corner of the + * passed rectangle, and use the maximum. + * + */ + public float furthestDistance(Rectangle r) { + float distanceSquared = 0; + + for (int i = 0; i < DIMENSIONS; i++) { + distanceSquared += Math.max(distanceSquared(i, r.min[i]), distanceSquared(i, r.max[i])); + } + + return (float) Math.sqrt(distanceSquared); + } + + /** + * Calculate the area by which this rectangle would be enlarged if + * added to the passed rectangle. Neither rectangle is altered. + * + * @param r Rectangle to union with this rectangle, in order to + * compute the difference in area of the union and the + * original rectangle + */ + public float enlargement(Rectangle r) { + float enlargedArea = (Math.max(max[0], r.max[0]) - Math.min(min[0], r.min[0])) * + (Math.max(max[1], r.max[1]) - Math.min(min[1], r.min[1])); + + return enlargedArea - area(); + } + + /** + * Compute the area of this rectangle. + * + * @return The area of this rectangle + */ + public float area() { + return (max[0] - min[0]) * (max[1] - min[1]); + } + + /** + * Computes the union of this rectangle and the passed rectangle, storing + * the result in this rectangle. + * + * @param r Rectangle to add to this rectangle + */ + public void add(Rectangle r) { + for (int i = 0; i < DIMENSIONS; i++) { + if (r.min[i] < min[i]) { + min[i] = r.min[i]; + } + if (r.max[i] > max[i]) { + max[i] = r.max[i]; + } + } + } + + /** + * Find the the union of this rectangle and the passed rectangle. + * Neither rectangle is altered + * + * @param r The rectangle to union with this rectangle + */ + public Rectangle union(Rectangle r) { + Rectangle union = this.copy(); + union.add(r); + return union; + } + + /** + * Determine whether this rectangle is equal to a given object. + * Equality is determined by the bounds of the rectangle. + * + * @param The object to compare with this rectangle + */ + public boolean equals(Object o) { + boolean equals = false; + if (o instanceof Rectangle) { + Rectangle r = (Rectangle) o; + if (Arrays.equals(r.min, min) && Arrays.equals(r.max, max)) { + equals = true; + } + } + return equals; + } + + /** + * Determine whether this rectangle is the same as another object + * + * Note that two rectangles can be equal but not the same object, + * if they both have the same bounds. + * + * @param o The object to compare with this rectangle. + */ + public boolean sameObject(Object o) { + return super.equals(o); + } + + /** + * Return a string representation of this rectangle, in the form: + * (1.2, 3.4), (5.6, 7.8) + * + * @return String String representation of this rectangle. + */ + public String toString() { + StringBuffer sb = new StringBuffer(); + + // min coordinates + sb.append('('); + for (int i = 0; i < DIMENSIONS; i++) { + if (i > 0) { + sb.append(", "); + } + sb.append(min[i]); + } + sb.append("), ("); + + // max coordinates + for (int i = 0; i < DIMENSIONS; i++) { + if (i > 0) { + sb.append(", "); + } + sb.append(max[i]); + } + sb.append(')'); + return sb.toString(); + } +}