--- /dev/null
+// Rectangle.java\r
+// Java Spatial Index Library\r
+// Copyright (C) 2002-2005 Infomatiq Limited\r
+// \r
+// This library is free software; you can redistribute it and/or\r
+// modify it under the terms of the GNU Lesser General Public\r
+// License as published by the Free Software Foundation; either\r
+// version 2.1 of the License, or (at your option) any later version.\r
+// \r
+// This library is distributed in the hope that it will be useful,\r
+// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
+// Lesser General Public License for more details.\r
+// \r
+// You should have received a copy of the GNU Lesser General Public\r
+// License along with this library; if not, write to the Free Software\r
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
+\r
+package com.infomatiq.jsi;\r
+\r
+\r
+\r
+/**\r
+ * Currently hardcoded to 2 dimensions, but could be extended.\r
+ * \r
+ * @author aled@sourceforge.net\r
+ * @version 1.0b8\r
+ */\r
+public class Rectangle {\r
+ \r
+ /**\r
+ * use primitives instead of arrays for the coordinates of the rectangle,\r
+ * to reduce memory requirements.\r
+ */\r
+ public float minX, minY, maxX, maxY;\r
+ \r
+ public Rectangle() {\r
+ minX = Float.MAX_VALUE;\r
+ minY = Float.MAX_VALUE;\r
+ maxX = -Float.MAX_VALUE;\r
+ maxY = -Float.MAX_VALUE;\r
+ }\r
+ \r
+ /**\r
+ * Constructor.\r
+ * \r
+ * @param x1 coordinate of any corner of the rectangle\r
+ * @param y1 (see x1)\r
+ * @param x2 coordinate of the opposite corner\r
+ * @param y2 (see x2)\r
+ */\r
+ public Rectangle(float x1, float y1, float x2, float y2) {\r
+ set(x1, y1, x2, y2);\r
+ }\r
+\r
+ /**\r
+ * Sets the size of the rectangle.\r
+ * \r
+ * @param x1 coordinate of any corner of the rectangle\r
+ * @param y1 (see x1)\r
+ * @param x2 coordinate of the opposite corner\r
+ * @param y2 (see x2)\r
+ */\r
+ public void set(float x1, float y1, float x2, float y2) {\r
+ minX = Math.min(x1, x2);\r
+ maxX = Math.max(x1, x2);\r
+ minY = Math.min(y1, y2);\r
+ maxY = Math.max(y1, y2);\r
+ }\r
+ \r
+ /**\r
+ * Sets the size of this rectangle to equal the passed rectangle.\r
+ */\r
+ public void set(Rectangle r) {\r
+ minX = r.minX;\r
+ minY = r.minY;\r
+ maxX = r.maxX;\r
+ maxY = r.maxY; \r
+ }\r
+ \r
+ /**\r
+ * Make a copy of this rectangle\r
+ * \r
+ * @return copy of this rectangle\r
+ */\r
+ public Rectangle copy() {\r
+ return new Rectangle(minX, minY, maxX, maxY); \r
+ }\r
+ \r
+ /**\r
+ * Determine whether an edge of this rectangle overlies the equivalent \r
+ * edge of the passed rectangle\r
+ */\r
+ public boolean edgeOverlaps(Rectangle r) {\r
+ return minX == r.minX || maxX == r.maxX || minY == r.minY || maxY == r.maxY;\r
+ }\r
+ \r
+ /**\r
+ * Determine whether this rectangle intersects the passed rectangle\r
+ * \r
+ * @param r The rectangle that might intersect this rectangle\r
+ * \r
+ * @return true if the rectangles intersect, false if they do not intersect\r
+ */\r
+ public boolean intersects(Rectangle r) {\r
+ return maxX >= r.minX && minX <= r.maxX && maxY >= r.minY && minY <= r.maxY;\r
+ }\r
+ \r
+ /**\r
+ * Determine whether or not two rectangles intersect\r
+ * \r
+ * @param r1MinX minimum X coordinate of rectangle 1\r
+ * @param r1MinY minimum Y coordinate of rectangle 1\r
+ * @param r1MaxX maximum X coordinate of rectangle 1\r
+ * @param r1MaxY maximum Y coordinate of rectangle 1\r
+ * @param r2MinX minimum X coordinate of rectangle 2\r
+ * @param r2MinY minimum Y coordinate of rectangle 2\r
+ * @param r2MaxX maximum X coordinate of rectangle 2\r
+ * @param r2MaxY maximum Y coordinate of rectangle 2\r
+ * \r
+ * @return true if r1 intersects r2, false otherwise.\r
+ */\r
+ static public boolean intersects(float r1MinX, float r1MinY, float r1MaxX, float r1MaxY,\r
+ float r2MinX, float r2MinY, float r2MaxX, float r2MaxY) { \r
+ return r1MaxX >= r2MinX && r1MinX <= r2MaxX && r1MaxY >= r2MinY && r1MinY <= r2MaxY; \r
+ }\r
+ \r
+ /**\r
+ * Determine whether this rectangle contains the passed rectangle\r
+ * \r
+ * @param r The rectangle that might be contained by this rectangle\r
+ * \r
+ * @return true if this rectangle contains the passed rectangle, false if\r
+ * it does not\r
+ */\r
+ public boolean contains(Rectangle r) {\r
+ return maxX >= r.maxX && minX <= r.minX && maxY >= r.maxY && minY <= r.minY; \r
+ }\r
+ \r
+ /**\r
+ * Determine whether or not one rectangle contains another.\r
+ * \r
+ * @param r1MinX minimum X coordinate of rectangle 1\r
+ * @param r1MinY minimum Y coordinate of rectangle 1\r
+ * @param r1MaxX maximum X coordinate of rectangle 1\r
+ * @param r1MaxY maximum Y coordinate of rectangle 1\r
+ * @param r2MinX minimum X coordinate of rectangle 2\r
+ * @param r2MinY minimum Y coordinate of rectangle 2\r
+ * @param r2MaxX maximum X coordinate of rectangle 2\r
+ * @param r2MaxY maximum Y coordinate of rectangle 2\r
+ * \r
+ * @return true if r1 contains r2, false otherwise.\r
+ */\r
+ static public boolean contains(float r1MinX, float r1MinY, float r1MaxX, float r1MaxY,\r
+ float r2MinX, float r2MinY, float r2MaxX, float r2MaxY) {\r
+ return r1MaxX >= r2MaxX && r1MinX <= r2MinX && r1MaxY >= r2MaxY && r1MinY <= r2MinY; \r
+ }\r
+ \r
+ /**\r
+ * Determine whether this rectangle is contained by the passed rectangle\r
+ * \r
+ * @param r The rectangle that might contain this rectangle\r
+ * \r
+ * @return true if the passed rectangle contains this rectangle, false if\r
+ * it does not\r
+ */\r
+ public boolean containedBy(Rectangle r) {\r
+ return r.maxX >= maxX && r.minX <= minX && r.maxY >= maxY && r.minY <= minY; \r
+ }\r
+ \r
+ /**\r
+ * Return the distance between this rectangle and the passed point.\r
+ * If the rectangle contains the point, the distance is zero.\r
+ * \r
+ * @param p Point to find the distance to\r
+ * \r
+ * @return distance beween this rectangle and the passed point.\r
+ */\r
+ public float distance(Point p) {\r
+ float distanceSquared = 0;\r
+ \r
+ float temp = minX - p.x;\r
+ if (temp < 0) {\r
+ temp = p.x - maxX;\r
+ }\r
+ \r
+ if (temp > 0) {\r
+ distanceSquared += (temp * temp);\r
+ }\r
+\r
+ temp = minY - p.y;\r
+ if (temp < 0) {\r
+ temp = p.y - maxY;\r
+ }\r
+\r
+ if (temp > 0) {\r
+ distanceSquared += (temp * temp);\r
+ }\r
+ \r
+ return (float) Math.sqrt(distanceSquared);\r
+ }\r
+ \r
+ /**\r
+ * Return the distance between a rectangle and a point.\r
+ * If the rectangle contains the point, the distance is zero.\r
+ * \r
+ * @param minX minimum X coordinate of rectangle\r
+ * @param minY minimum Y coordinate of rectangle\r
+ * @param maxX maximum X coordinate of rectangle\r
+ * @param maxY maximum Y coordinate of rectangle\r
+ * @param pX X coordinate of point\r
+ * @param pY Y coordinate of point\r
+ * \r
+ * @return distance beween this rectangle and the passed point.\r
+ */\r
+ static public float distance(float minX, float minY, float maxX, float maxY, float pX, float pY) {\r
+ return (float) Math.sqrt(distanceSq(minX, minY, maxX, maxY, pX, pY));\r
+ }\r
+ \r
+ static public float distanceSq(float minX, float minY, float maxX, float maxY, float pX, float pY) {\r
+ float distanceSqX = 0;\r
+ float distanceSqY = 0;\r
+ \r
+ if (minX > pX) {\r
+ distanceSqX = minX - pX;\r
+ distanceSqX *= distanceSqX;\r
+ } else if (pX > maxX) {\r
+ distanceSqX = pX - maxX;\r
+ distanceSqX *= distanceSqX;\r
+ }\r
+ \r
+ if (minY > pY) {\r
+ distanceSqY = minY - pY;\r
+ distanceSqY *= distanceSqY;\r
+ } else if (pY > maxY) {\r
+ distanceSqY = pY - maxY;\r
+ distanceSqY *= distanceSqY;\r
+ }\r
+ \r
+ return distanceSqX + distanceSqY;\r
+ }\r
+ \r
+ /**\r
+ * Return the distance between this rectangle and the passed rectangle.\r
+ * If the rectangles overlap, the distance is zero.\r
+ * \r
+ * @param r Rectangle to find the distance to\r
+ * \r
+ * @return distance between this rectangle and the passed rectangle\r
+ */\r
+\r
+ public float distance(Rectangle r) {\r
+ float distanceSquared = 0;\r
+ float greatestMin = Math.max(minX, r.minX);\r
+ float leastMax = Math.min(maxX, r.maxX);\r
+ if (greatestMin > leastMax) {\r
+ distanceSquared += ((greatestMin - leastMax) * (greatestMin - leastMax)); \r
+ }\r
+ greatestMin = Math.max(minY, r.minY);\r
+ leastMax = Math.min(maxY, r.maxY);\r
+ if (greatestMin > leastMax) {\r
+ distanceSquared += ((greatestMin - leastMax) * (greatestMin - leastMax)); \r
+ }\r
+ return (float) Math.sqrt(distanceSquared);\r
+ }\r
+\r
+ /**\r
+ * Calculate the area by which this rectangle would be enlarged if\r
+ * added to the passed rectangle. Neither rectangle is altered.\r
+ * \r
+ * @param r Rectangle to union with this rectangle, in order to \r
+ * compute the difference in area of the union and the\r
+ * original rectangle\r
+ * \r
+ * @return enlargement\r
+ */\r
+ public float enlargement(Rectangle r) {\r
+ float enlargedArea = (Math.max(maxX, r.maxX) - Math.min(minX, r.minX)) *\r
+ (Math.max(maxY, r.maxY) - Math.min(minY, r.minY));\r
+ \r
+ return enlargedArea - area();\r
+ }\r
+ \r
+ /**\r
+ * Calculate the area by which a rectangle would be enlarged if\r
+ * added to the passed rectangle..\r
+ * \r
+ * @param r1MinX minimum X coordinate of rectangle 1\r
+ * @param r1MinY minimum Y coordinate of rectangle 1\r
+ * @param r1MaxX maximum X coordinate of rectangle 1\r
+ * @param r1MaxY maximum Y coordinate of rectangle 1\r
+ * @param r2MinX minimum X coordinate of rectangle 2\r
+ * @param r2MinY minimum Y coordinate of rectangle 2\r
+ * @param r2MaxX maximum X coordinate of rectangle 2\r
+ * @param r2MaxY maximum Y coordinate of rectangle 2\r
+ * \r
+ * @return enlargement\r
+ */\r
+ static public float enlargement(float r1MinX, float r1MinY, float r1MaxX, float r1MaxY,\r
+ float r2MinX, float r2MinY, float r2MaxX, float r2MaxY) { \r
+ float r1Area = (r1MaxX - r1MinX) * (r1MaxY - r1MinY); \r
+ \r
+ if (r1Area == Float.POSITIVE_INFINITY) {\r
+ return 0; // cannot enlarge an infinite rectangle...\r
+ }\r
+ \r
+ if (r2MinX < r1MinX) r1MinX = r2MinX; \r
+ if (r2MinY < r1MinY) r1MinY = r2MinY; \r
+ if (r2MaxX > r1MaxX) r1MaxX = r2MaxX; \r
+ if (r2MaxY > r1MaxY) r1MaxY = r2MaxY;\r
+ \r
+ float r1r2UnionArea = (r1MaxX - r1MinX) * (r1MaxY - r1MinY);\r
+ \r
+ if (r1r2UnionArea == Float.POSITIVE_INFINITY) {\r
+ // if a finite rectangle is enlarged and becomes infinite,\r
+ // then the enlargement must be infinite.\r
+ return Float.POSITIVE_INFINITY;\r
+ }\r
+ return r1r2UnionArea - r1Area; \r
+ }\r
+ \r
+ /**\r
+ * Compute the area of this rectangle.\r
+ * \r
+ * @return The area of this rectangle\r
+ */\r
+ public float area() {\r
+ return (maxX - minX) * (maxY - minY);\r
+ }\r
+ \r
+ /**\r
+ * Compute the area of a rectangle.\r
+ * \r
+ * @param minX the minimum X coordinate of the rectangle\r
+ * @param minY the minimum Y coordinate of the rectangle\r
+ * @param maxX the maximum X coordinate of the rectangle\r
+ * @param maxY the maximum Y coordinate of the rectangle\r
+ * \r
+ * @return The area of the rectangle\r
+ */\r
+ static public float area(float minX, float minY, float maxX, float maxY) {\r
+ return (maxX - minX) * (maxY - minY);\r
+ }\r
+ \r
+ /**\r
+ * Computes the union of this rectangle and the passed rectangle, storing\r
+ * the result in this rectangle.\r
+ * \r
+ * @param r Rectangle to add to this rectangle\r
+ */\r
+ public void add(Rectangle r) {\r
+ if (r.minX < minX) minX = r.minX;\r
+ if (r.maxX > maxX) maxX = r.maxX;\r
+ if (r.minY < minY) minY = r.minY;\r
+ if (r.maxY > maxY) maxY = r.maxY;\r
+ }\r
+ \r
+ /**\r
+ * Computes the union of this rectangle and the passed point, storing\r
+ * the result in this rectangle.\r
+ * \r
+ * @param p Point to add to this rectangle\r
+ */\r
+ public void add(Point p) {\r
+ if (p.x < minX) minX = p.x;\r
+ if (p.x > maxX) maxX = p.x;\r
+ if (p.y < minY) minY = p.y;\r
+ if (p.y > maxY) maxY = p.y;\r
+ }\r
+ \r
+ /**\r
+ * Find the the union of this rectangle and the passed rectangle.\r
+ * Neither rectangle is altered\r
+ * \r
+ * @param r The rectangle to union with this rectangle\r
+ */\r
+ public Rectangle union(Rectangle r) {\r
+ Rectangle union = this.copy();\r
+ union.add(r);\r
+ return union; \r
+ }\r
+ \r
+ /**\r
+ * Determine whether this rectangle is equal to a given object.\r
+ * Equality is determined by the bounds of the rectangle.\r
+ * \r
+ * @param o The object to compare with this rectangle\r
+ */\r
+ public boolean equals(Object o) {\r
+ boolean equals = false;\r
+ if (o instanceof Rectangle) {\r
+ Rectangle r = (Rectangle) o;\r
+ if (minX == r.minX && minY == r.minY && maxX == r.maxX && maxY == r.maxY) {\r
+ equals = true;\r
+ }\r
+ } \r
+ return equals; \r
+ }\r
+\r
+ /** \r
+ * Determine whether this rectangle is the same as another object\r
+ * \r
+ * Note that two rectangles can be equal but not the same object, \r
+ * if they both have the same bounds.\r
+ * \r
+ * @param o The object to compare with this rectangle.\r
+ */ \r
+ public boolean sameObject(Object o) {\r
+ return super.equals(o); \r
+ }\r
+ \r
+ /**\r
+ * Return a string representation of this rectangle, in the form: \r
+ * (1.2, 3.4), (5.6, 7.8)\r
+ * \r
+ * @return String String representation of this rectangle.\r
+ */\r
+ public String toString() {\r
+ return "(" + minX + ", " + minY + "), (" + maxX + ", " + maxY + ")";\r
+ }\r
+ \r
+ /**\r
+ * Utility methods (not used by JSI); added to \r
+ * enable this to be used as a generic rectangle class \r
+ */\r
+ public float width() {\r
+ return maxX - minX;\r
+ }\r
+ \r
+ public float height() {\r
+ return maxY - minY;\r
+ }\r
+ \r
+ public float aspectRatio() {\r
+ return width() / height();\r
+ }\r
+ \r
+ public Point centre() {\r
+ return new Point((minX + maxX) / 2, (minY + maxY) / 2);\r
+ }\r
+ \r
+}\r