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