2 // Java Spatial Index Library
3 // Copyright (C) 2002-2005 Infomatiq Limited
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2.1 of the License, or (at your option) any later version.
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // Lesser General Public License for more details.
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 package com.infomatiq.jsi;
24 * Currently hardcoded to 2 dimensions, but could be extended.
26 * @author aled@sourceforge.net
29 public class Rectangle {
32 * use primitives instead of arrays for the coordinates of the rectangle,
33 * to reduce memory requirements.
35 public float minX, minY, maxX, maxY;
38 minX = Float.MAX_VALUE;
39 minY = Float.MAX_VALUE;
40 maxX = -Float.MAX_VALUE;
41 maxY = -Float.MAX_VALUE;
47 * @param x1 coordinate of any corner of the rectangle
49 * @param x2 coordinate of the opposite corner
52 public Rectangle(float x1, float y1, float x2, float y2) {
57 * Sets the size of the rectangle.
59 * @param x1 coordinate of any corner of the rectangle
61 * @param x2 coordinate of the opposite corner
64 public void set(float x1, float y1, float x2, float y2) {
65 minX = Math.min(x1, x2);
66 maxX = Math.max(x1, x2);
67 minY = Math.min(y1, y2);
68 maxY = Math.max(y1, y2);
72 * Sets the size of this rectangle to equal the passed rectangle.
74 public void set(Rectangle r) {
82 * Make a copy of this rectangle
84 * @return copy of this rectangle
86 public Rectangle copy() {
87 return new Rectangle(minX, minY, maxX, maxY);
91 * Determine whether an edge of this rectangle overlies the equivalent
92 * edge of the passed rectangle
94 public boolean edgeOverlaps(Rectangle r) {
95 return minX == r.minX || maxX == r.maxX || minY == r.minY || maxY == r.maxY;
99 * Determine whether this rectangle intersects the passed rectangle
101 * @param r The rectangle that might intersect this rectangle
103 * @return true if the rectangles intersect, false if they do not intersect
105 public boolean intersects(Rectangle r) {
106 return maxX >= r.minX && minX <= r.maxX && maxY >= r.minY && minY <= r.maxY;
110 * Determine whether or not two rectangles intersect
112 * @param r1MinX minimum X coordinate of rectangle 1
113 * @param r1MinY minimum Y coordinate of rectangle 1
114 * @param r1MaxX maximum X coordinate of rectangle 1
115 * @param r1MaxY maximum Y coordinate of rectangle 1
116 * @param r2MinX minimum X coordinate of rectangle 2
117 * @param r2MinY minimum Y coordinate of rectangle 2
118 * @param r2MaxX maximum X coordinate of rectangle 2
119 * @param r2MaxY maximum Y coordinate of rectangle 2
121 * @return true if r1 intersects r2, false otherwise.
123 static public boolean intersects(float r1MinX, float r1MinY, float r1MaxX, float r1MaxY,
124 float r2MinX, float r2MinY, float r2MaxX, float r2MaxY) {
125 return r1MaxX >= r2MinX && r1MinX <= r2MaxX && r1MaxY >= r2MinY && r1MinY <= r2MaxY;
129 * Determine whether this rectangle contains the passed rectangle
131 * @param r The rectangle that might be contained by this rectangle
133 * @return true if this rectangle contains the passed rectangle, false if
136 public boolean contains(Rectangle r) {
137 return maxX >= r.maxX && minX <= r.minX && maxY >= r.maxY && minY <= r.minY;
141 * Determine whether or not one rectangle contains another.
143 * @param r1MinX minimum X coordinate of rectangle 1
144 * @param r1MinY minimum Y coordinate of rectangle 1
145 * @param r1MaxX maximum X coordinate of rectangle 1
146 * @param r1MaxY maximum Y coordinate of rectangle 1
147 * @param r2MinX minimum X coordinate of rectangle 2
148 * @param r2MinY minimum Y coordinate of rectangle 2
149 * @param r2MaxX maximum X coordinate of rectangle 2
150 * @param r2MaxY maximum Y coordinate of rectangle 2
152 * @return true if r1 contains r2, false otherwise.
154 static public boolean contains(float r1MinX, float r1MinY, float r1MaxX, float r1MaxY,
155 float r2MinX, float r2MinY, float r2MaxX, float r2MaxY) {
156 return r1MaxX >= r2MaxX && r1MinX <= r2MinX && r1MaxY >= r2MaxY && r1MinY <= r2MinY;
160 * Determine whether this rectangle is contained by the passed rectangle
162 * @param r The rectangle that might contain this rectangle
164 * @return true if the passed rectangle contains this rectangle, false if
167 public boolean containedBy(Rectangle r) {
168 return r.maxX >= maxX && r.minX <= minX && r.maxY >= maxY && r.minY <= minY;
172 * Return the distance between this rectangle and the passed point.
173 * If the rectangle contains the point, the distance is zero.
175 * @param p Point to find the distance to
177 * @return distance beween this rectangle and the passed point.
179 public float distance(Point p) {
180 float distanceSquared = 0;
182 float temp = minX - p.x;
188 distanceSquared += (temp * temp);
197 distanceSquared += (temp * temp);
200 return (float) Math.sqrt(distanceSquared);
204 * Return the distance between a rectangle and a point.
205 * If the rectangle contains the point, the distance is zero.
207 * @param minX minimum X coordinate of rectangle
208 * @param minY minimum Y coordinate of rectangle
209 * @param maxX maximum X coordinate of rectangle
210 * @param maxY maximum Y coordinate of rectangle
211 * @param pX X coordinate of point
212 * @param pY Y coordinate of point
214 * @return distance beween this rectangle and the passed point.
216 static public float distance(float minX, float minY, float maxX, float maxY, float pX, float pY) {
217 return (float) Math.sqrt(distanceSq(minX, minY, maxX, maxY, pX, pY));
220 static public float distanceSq(float minX, float minY, float maxX, float maxY, float pX, float pY) {
221 float distanceSqX = 0;
222 float distanceSqY = 0;
225 distanceSqX = minX - pX;
226 distanceSqX *= distanceSqX;
227 } else if (pX > maxX) {
228 distanceSqX = pX - maxX;
229 distanceSqX *= distanceSqX;
233 distanceSqY = minY - pY;
234 distanceSqY *= distanceSqY;
235 } else if (pY > maxY) {
236 distanceSqY = pY - maxY;
237 distanceSqY *= distanceSqY;
240 return distanceSqX + distanceSqY;
244 * Return the distance between this rectangle and the passed rectangle.
245 * If the rectangles overlap, the distance is zero.
247 * @param r Rectangle to find the distance to
249 * @return distance between this rectangle and the passed rectangle
252 public float distance(Rectangle r) {
253 float distanceSquared = 0;
254 float greatestMin = Math.max(minX, r.minX);
255 float leastMax = Math.min(maxX, r.maxX);
256 if (greatestMin > leastMax) {
257 distanceSquared += ((greatestMin - leastMax) * (greatestMin - leastMax));
259 greatestMin = Math.max(minY, r.minY);
260 leastMax = Math.min(maxY, r.maxY);
261 if (greatestMin > leastMax) {
262 distanceSquared += ((greatestMin - leastMax) * (greatestMin - leastMax));
264 return (float) Math.sqrt(distanceSquared);
268 * Calculate the area by which this rectangle would be enlarged if
269 * added to the passed rectangle. Neither rectangle is altered.
271 * @param r Rectangle to union with this rectangle, in order to
272 * compute the difference in area of the union and the
275 * @return enlargement
277 public float enlargement(Rectangle r) {
278 float enlargedArea = (Math.max(maxX, r.maxX) - Math.min(minX, r.minX)) *
279 (Math.max(maxY, r.maxY) - Math.min(minY, r.minY));
281 return enlargedArea - area();
285 * Calculate the area by which a rectangle would be enlarged if
286 * added to the passed rectangle..
288 * @param r1MinX minimum X coordinate of rectangle 1
289 * @param r1MinY minimum Y coordinate of rectangle 1
290 * @param r1MaxX maximum X coordinate of rectangle 1
291 * @param r1MaxY maximum Y coordinate of rectangle 1
292 * @param r2MinX minimum X coordinate of rectangle 2
293 * @param r2MinY minimum Y coordinate of rectangle 2
294 * @param r2MaxX maximum X coordinate of rectangle 2
295 * @param r2MaxY maximum Y coordinate of rectangle 2
297 * @return enlargement
299 static public float enlargement(float r1MinX, float r1MinY, float r1MaxX, float r1MaxY,
300 float r2MinX, float r2MinY, float r2MaxX, float r2MaxY) {
301 float r1Area = (r1MaxX - r1MinX) * (r1MaxY - r1MinY);
303 if (r1Area == Float.POSITIVE_INFINITY) {
304 return 0; // cannot enlarge an infinite rectangle...
307 if (r2MinX < r1MinX) r1MinX = r2MinX;
308 if (r2MinY < r1MinY) r1MinY = r2MinY;
309 if (r2MaxX > r1MaxX) r1MaxX = r2MaxX;
310 if (r2MaxY > r1MaxY) r1MaxY = r2MaxY;
312 float r1r2UnionArea = (r1MaxX - r1MinX) * (r1MaxY - r1MinY);
314 if (r1r2UnionArea == Float.POSITIVE_INFINITY) {
315 // if a finite rectangle is enlarged and becomes infinite,
316 // then the enlargement must be infinite.
317 return Float.POSITIVE_INFINITY;
319 return r1r2UnionArea - r1Area;
323 * Compute the area of this rectangle.
325 * @return The area of this rectangle
327 public float area() {
328 return (maxX - minX) * (maxY - minY);
332 * Compute the area of a rectangle.
334 * @param minX the minimum X coordinate of the rectangle
335 * @param minY the minimum Y coordinate of the rectangle
336 * @param maxX the maximum X coordinate of the rectangle
337 * @param maxY the maximum Y coordinate of the rectangle
339 * @return The area of the rectangle
341 static public float area(float minX, float minY, float maxX, float maxY) {
342 return (maxX - minX) * (maxY - minY);
346 * Computes the union of this rectangle and the passed rectangle, storing
347 * the result in this rectangle.
349 * @param r Rectangle to add to this rectangle
351 public void add(Rectangle r) {
352 if (r.minX < minX) minX = r.minX;
353 if (r.maxX > maxX) maxX = r.maxX;
354 if (r.minY < minY) minY = r.minY;
355 if (r.maxY > maxY) maxY = r.maxY;
359 * Computes the union of this rectangle and the passed point, storing
360 * the result in this rectangle.
362 * @param p Point to add to this rectangle
364 public void add(Point p) {
365 if (p.x < minX) minX = p.x;
366 if (p.x > maxX) maxX = p.x;
367 if (p.y < minY) minY = p.y;
368 if (p.y > maxY) maxY = p.y;
372 * Find the the union of this rectangle and the passed rectangle.
373 * Neither rectangle is altered
375 * @param r The rectangle to union with this rectangle
377 public Rectangle union(Rectangle r) {
378 Rectangle union = this.copy();
384 * Determine whether this rectangle is equal to a given object.
385 * Equality is determined by the bounds of the rectangle.
387 * @param o The object to compare with this rectangle
389 public boolean equals(Object o) {
390 boolean equals = false;
391 if (o instanceof Rectangle) {
392 Rectangle r = (Rectangle) o;
393 if (minX == r.minX && minY == r.minY && maxX == r.maxX && maxY == r.maxY) {
401 * Determine whether this rectangle is the same as another object
403 * Note that two rectangles can be equal but not the same object,
404 * if they both have the same bounds.
406 * @param o The object to compare with this rectangle.
408 public boolean sameObject(Object o) {
409 return super.equals(o);
413 * Return a string representation of this rectangle, in the form:
414 * (1.2, 3.4), (5.6, 7.8)
416 * @return String String representation of this rectangle.
418 public String toString() {
419 return "(" + minX + ", " + minY + "), (" + maxX + ", " + maxY + ")";
423 * Utility methods (not used by JSI); added to
424 * enable this to be used as a generic rectangle class
426 public float width() {
430 public float height() {
434 public float aspectRatio() {
435 return width() / height();
438 public Point centre() {
439 return new Point((minX + maxX) / 2, (minY + maxY) / 2);