Frames | No Frames |
1: /* Rectangle2D.java -- generic rectangles in 2-D space 2: Copyright (C) 2000, 2001, 2002, 2004 Free Software Foundation 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package java.awt.geom; 40: 41: import java.util.NoSuchElementException; 42: 43: /** 44: * This class describes a rectangle by a point (x,y) and dimension (w x h). 45: * The actual storage is left up to subclasses. 46: * 47: * <p>It is valid for a rectangle to have negative width or height; but it 48: * is considered to have no area or internal points. Therefore, the behavior 49: * in methods like <code>contains</code> or <code>intersects</code> is 50: * undefined unless the rectangle has positive width and height. 51: * 52: * @author Tom Tromey (tromey@cygnus.com) 53: * @author Eric Blake (ebb9@email.byu.edu) 54: * @since 1.2 55: * @status updated to 1.4 56: */ 57: public abstract class Rectangle2D extends RectangularShape 58: { 59: /** 60: * The point lies left of the rectangle (p.x < r.x). 61: * 62: * @see #outcode(double, double) 63: */ 64: public static final int OUT_LEFT = 1; 65: 66: /** 67: * The point lies above the rectangle (p.y < r.y). 68: * 69: * @see #outcode(double, double) 70: */ 71: public static final int OUT_TOP = 2; 72: 73: /** 74: * The point lies right of the rectangle (p.x > r.maxX). 75: * 76: * @see #outcode(double, double) 77: */ 78: public static final int OUT_RIGHT = 4; 79: 80: /** 81: * The point lies below of the rectangle (p.y > r.maxY). 82: * 83: * @see #outcode(double, double) 84: */ 85: public static final int OUT_BOTTOM = 8; 86: 87: /** 88: * Default constructor. 89: */ 90: protected Rectangle2D() 91: { 92: } 93: 94: /** 95: * Set the bounding box of this rectangle. 96: * 97: * @param x the new X coordinate 98: * @param y the new Y coordinate 99: * @param w the new width 100: * @param h the new height 101: */ 102: public abstract void setRect(double x, double y, double w, double h); 103: 104: /** 105: * Set the bounding box of this rectangle from the given one. 106: * 107: * @param r rectangle to copy 108: * @throws NullPointerException if r is null 109: */ 110: public void setRect(Rectangle2D r) 111: { 112: setRect(r.getX(), r.getY(), r.getWidth(), r.getHeight()); 113: } 114: 115: /** 116: * Tests if the specified line intersects the interior of this rectangle. 117: * 118: * @param x1 the first x coordinate of line segment 119: * @param y1 the first y coordinate of line segment 120: * @param x2 the second x coordinate of line segment 121: * @param y2 the second y coordinate of line segment 122: * @return true if the line intersects the rectangle 123: */ 124: public boolean intersectsLine(double x1, double y1, double x2, double y2) 125: { 126: double x = getX(); 127: double y = getY(); 128: double w = getWidth(); 129: double h = getHeight(); 130: if (w <= 0 || h <= 0) 131: return false; 132: 133: if (x1 >= x && x1 <= x + w && y1 >= y && y1 <= y + h) 134: return true; 135: if (x2 >= x && x2 <= x + w && y2 >= y && y2 <= y + h) 136: return true; 137: 138: double x3 = x + w; 139: double y3 = y + h; 140: 141: return (Line2D.linesIntersect(x1, y1, x2, y2, x, y, x, y3) 142: || Line2D.linesIntersect(x1, y1, x2, y2, x, y3, x3, y3) 143: || Line2D.linesIntersect(x1, y1, x2, y2, x3, y3, x3, y) 144: || Line2D.linesIntersect(x1, y1, x2, y2, x3, y, x, y)); 145: } 146: 147: /** 148: * Tests if the specified line intersects the interior of this rectangle. 149: * 150: * @param l the line segment 151: * @return true if the line intersects the rectangle 152: * @throws NullPointerException if l is null 153: */ 154: public boolean intersectsLine(Line2D l) 155: { 156: return intersectsLine(l.getX1(), l.getY1(), l.getX2(), l.getY2()); 157: } 158: 159: /** 160: * Determine where the point lies with respect to this rectangle. The 161: * result will be the binary OR of the appropriate bit masks. 162: * 163: * @param x the x coordinate to check 164: * @param y the y coordinate to check 165: * @return the binary OR of the result 166: * @see #OUT_LEFT 167: * @see #OUT_TOP 168: * @see #OUT_RIGHT 169: * @see #OUT_BOTTOM 170: */ 171: public abstract int outcode(double x, double y); 172: 173: /** 174: * Determine where the point lies with respect to this rectangle. The 175: * result will be the binary OR of the appropriate bit masks. 176: * 177: * @param p the point to check 178: * @return the binary OR of the result 179: * @throws NullPointerException if p is null 180: * @see #OUT_LEFT 181: * @see #OUT_TOP 182: * @see #OUT_RIGHT 183: * @see #OUT_BOTTOM 184: */ 185: public int outcode(Point2D p) 186: { 187: return outcode(p.getX(), p.getY()); 188: } 189: 190: /** 191: * Set the bounding box of this rectangle. 192: * 193: * @param x the new X coordinate 194: * @param y the new Y coordinate 195: * @param w the new width 196: * @param h the new height 197: */ 198: public void setFrame(double x, double y, double w, double h) 199: { 200: setRect(x, y, w, h); 201: } 202: 203: /** 204: * Returns the bounds of this rectangle. A pretty useless method, as this 205: * is already a rectangle. 206: * 207: * @return a copy of this rectangle 208: */ 209: public Rectangle2D getBounds2D() 210: { 211: return (Rectangle2D) clone(); 212: } 213: 214: /** 215: * Test if the given point is contained in the rectangle. 216: * 217: * @param x the x coordinate of the point 218: * @param y the y coordinate of the point 219: * @return true if (x,y) is in the rectangle 220: */ 221: public boolean contains(double x, double y) 222: { 223: double mx = getX(); 224: double my = getY(); 225: double w = getWidth(); 226: double h = getHeight(); 227: return w > 0 && h > 0 && x >= mx && x < mx + w && y >= my && y < my + h; 228: } 229: 230: /** 231: * Tests if the given rectangle intersects this one. In other words, test if 232: * the two rectangles share at least one internal point. 233: * 234: * @param x the x coordinate of the other rectangle 235: * @param y the y coordinate of the other rectangle 236: * @param w the width of the other rectangle 237: * @param h the height of the other rectangle 238: * @return true if the rectangles intersect 239: */ 240: public boolean intersects(double x, double y, double w, double h) 241: { 242: double mx = getX(); 243: double my = getY(); 244: double mw = getWidth(); 245: double mh = getHeight(); 246: return w > 0 && h > 0 && mw > 0 && mh > 0 247: && x < mx + mw && x + w > mx && y < my + mh && y + h > my; 248: } 249: 250: /** 251: * Tests if this rectangle contains the given one. In other words, test if 252: * this rectangle contains all points in the given one. 253: * 254: * @param x the x coordinate of the other rectangle 255: * @param y the y coordinate of the other rectangle 256: * @param w the width of the other rectangle 257: * @param h the height of the other rectangle 258: * @return true if this rectangle contains the other 259: */ 260: public boolean contains(double x, double y, double w, double h) 261: { 262: double mx = getX(); 263: double my = getY(); 264: double mw = getWidth(); 265: double mh = getHeight(); 266: return w > 0 && h > 0 && mw > 0 && mh > 0 267: && x >= mx && x + w <= mx + mw && y >= my && y + h <= my + mh; 268: } 269: 270: /** 271: * Return a new rectangle which is the intersection of this and the given 272: * one. The result will be empty if there is no intersection. 273: * 274: * @param r the rectangle to be intersected 275: * @return the intersection 276: * @throws NullPointerException if r is null 277: */ 278: public abstract Rectangle2D createIntersection(Rectangle2D r); 279: 280: /** 281: * Intersects a pair of rectangles, and places the result in the 282: * destination; this can be used to avoid object creation. This method 283: * even works when the destination is also a source, although you stand 284: * to lose the original data. 285: * 286: * @param src1 the first source 287: * @param src2 the second source 288: * @param dest the destination for the intersection 289: * @throws NullPointerException if any rectangle is null 290: */ 291: public static void intersect(Rectangle2D src1, Rectangle2D src2, 292: Rectangle2D dest) 293: { 294: double x = Math.max(src1.getX(), src2.getX()); 295: double y = Math.max(src1.getY(), src2.getY()); 296: double maxx = Math.min(src1.getMaxX(), src2.getMaxX()); 297: double maxy = Math.min(src1.getMaxY(), src2.getMaxY()); 298: dest.setRect(x, y, maxx - x, maxy - y); 299: } 300: 301: /** 302: * Return a new rectangle which is the union of this and the given one. 303: * 304: * @param r the rectangle to be merged 305: * @return the union 306: * @throws NullPointerException if r is null 307: */ 308: public abstract Rectangle2D createUnion(Rectangle2D r); 309: 310: /** 311: * Joins a pair of rectangles, and places the result in the destination; 312: * this can be used to avoid object creation. This method even works when 313: * the destination is also a source, although you stand to lose the 314: * original data. 315: * 316: * @param src1 the first source 317: * @param src2 the second source 318: * @param dest the destination for the union 319: * @throws NullPointerException if any rectangle is null 320: */ 321: public static void union(Rectangle2D src1, Rectangle2D src2, 322: Rectangle2D dest) 323: { 324: double x = Math.min(src1.getX(), src2.getX()); 325: double y = Math.min(src1.getY(), src2.getY()); 326: double maxx = Math.max(src1.getMaxX(), src2.getMaxX()); 327: double maxy = Math.max(src1.getMaxY(), src2.getMaxY()); 328: dest.setRect(x, y, maxx - x, maxy - y); 329: } 330: 331: /** 332: * Modifies this rectangle so that it represents the smallest rectangle 333: * that contains both the existing rectangle and the specified point. 334: * However, if the point falls on one of the two borders which are not 335: * inside the rectangle, a subsequent call to <code>contains</code> may 336: * return false. 337: * 338: * @param newx the X coordinate of the point to add to this rectangle 339: * @param newy the Y coordinate of the point to add to this rectangle 340: */ 341: public void add(double newx, double newy) 342: { 343: double minx = Math.min(getX(), newx); 344: double maxx = Math.max(getMaxX(), newx); 345: double miny = Math.min(getY(), newy); 346: double maxy = Math.max(getMaxY(), newy); 347: setRect(minx, miny, maxx - minx, maxy - miny); 348: } 349: 350: /** 351: * Modifies this rectangle so that it represents the smallest rectangle 352: * that contains both the existing rectangle and the specified point. 353: * However, if the point falls on one of the two borders which are not 354: * inside the rectangle, a subsequent call to <code>contains</code> may 355: * return false. 356: * 357: * @param p the point to add to this rectangle 358: * @throws NullPointerException if p is null 359: */ 360: public void add(Point2D p) 361: { 362: add(p.getX(), p.getY()); 363: } 364: 365: /** 366: * Modifies this rectangle so that it represents the smallest rectangle 367: * that contains both the existing rectangle and the specified rectangle. 368: * 369: * @param r the rectangle to add to this rectangle 370: * @throws NullPointerException if r is null 371: * @see #union(Rectangle2D, Rectangle2D, Rectangle2D) 372: */ 373: public void add(Rectangle2D r) 374: { 375: union(this, r, this); 376: } 377: 378: /** 379: * Return an iterator along the shape boundary. If the optional transform 380: * is provided, the iterator is transformed accordingly. Each call returns 381: * a new object, independent from others in use. This iterator is thread 382: * safe; modifications to the rectangle do not affect the results of this 383: * path instance. 384: * 385: * @param at an optional transform to apply to the iterator 386: * @return a new iterator over the boundary 387: * @since 1.2 388: */ 389: public PathIterator getPathIterator(final AffineTransform at) 390: { 391: final double minx = getX(); 392: final double miny = getY(); 393: final double maxx = minx + getWidth(); 394: final double maxy = miny + getHeight(); 395: return new PathIterator() 396: { 397: /** Current coordinate. */ 398: private int current = (maxx <= minx && maxy <= miny) ? 6 : 0; 399: 400: public int getWindingRule() 401: { 402: // A test program showed that Sun J2SE 1.3.1 and 1.4.1_01 403: // return WIND_NON_ZERO paths. While this does not really 404: // make any difference for rectangles (because they are not 405: // self-intersecting), it seems appropriate to behave 406: // identically. 407: 408: return WIND_NON_ZERO; 409: } 410: 411: public boolean isDone() 412: { 413: return current > 5; 414: } 415: 416: public void next() 417: { 418: current++; 419: } 420: 421: public int currentSegment(float[] coords) 422: { 423: switch (current) 424: { 425: case 1: 426: coords[0] = (float) maxx; 427: coords[1] = (float) miny; 428: break; 429: case 2: 430: coords[0] = (float) maxx; 431: coords[1] = (float) maxy; 432: break; 433: case 3: 434: coords[0] = (float) minx; 435: coords[1] = (float) maxy; 436: break; 437: case 0: 438: case 4: 439: coords[0] = (float) minx; 440: coords[1] = (float) miny; 441: break; 442: case 5: 443: return SEG_CLOSE; 444: default: 445: throw new NoSuchElementException("rect iterator out of bounds"); 446: } 447: if (at != null) 448: at.transform(coords, 0, coords, 0, 1); 449: return current == 0 ? SEG_MOVETO : SEG_LINETO; 450: } 451: 452: public int currentSegment(double[] coords) 453: { 454: switch (current) 455: { 456: case 1: 457: coords[0] = maxx; 458: coords[1] = miny; 459: break; 460: case 2: 461: coords[0] = maxx; 462: coords[1] = maxy; 463: break; 464: case 3: 465: coords[0] = minx; 466: coords[1] = maxy; 467: break; 468: case 0: 469: case 4: 470: coords[0] = minx; 471: coords[1] = miny; 472: break; 473: case 5: 474: return SEG_CLOSE; 475: default: 476: throw new NoSuchElementException("rect iterator out of bounds"); 477: } 478: if (at != null) 479: at.transform(coords, 0, coords, 0, 1); 480: return current == 0 ? SEG_MOVETO : SEG_LINETO; 481: } 482: }; 483: } 484: 485: /** 486: * Return an iterator along the shape boundary. If the optional transform 487: * is provided, the iterator is transformed accordingly. Each call returns 488: * a new object, independent from others in use. This iterator is thread 489: * safe; modifications to the rectangle do not affect the results of this 490: * path instance. As the rectangle is already flat, the flatness parameter 491: * is ignored. 492: * 493: * @param at an optional transform to apply to the iterator 494: * @param flatness the maximum distance for deviation from the real boundary 495: * @return a new iterator over the boundary 496: * @since 1.2 497: */ 498: public PathIterator getPathIterator(AffineTransform at, double flatness) 499: { 500: return getPathIterator(at); 501: } 502: 503: /** 504: * Return the hashcode for this rectangle. The formula is not documented, but 505: * appears to be the same as: 506: * <pre> 507: * long l = Double.doubleToLongBits(getX()) 508: * + 37 * Double.doubleToLongBits(getY()) 509: * + 43 * Double.doubleToLongBits(getWidth()) 510: * + 47 * Double.doubleToLongBits(getHeight()); 511: * return (int) ((l >> 32) ^ l); 512: * </pre> 513: * 514: * @return the hashcode 515: */ 516: public int hashCode() 517: { 518: // Talk about a fun time reverse engineering this one! 519: long l = java.lang.Double.doubleToLongBits(getX()) 520: + 37 * java.lang.Double.doubleToLongBits(getY()) 521: + 43 * java.lang.Double.doubleToLongBits(getWidth()) 522: + 47 * java.lang.Double.doubleToLongBits(getHeight()); 523: return (int) ((l >> 32) ^ l); 524: } 525: 526: /** 527: * Tests this rectangle for equality against the specified object. This 528: * will be true if an only if the specified object is an instance of 529: * Rectangle2D with the same coordinates and dimensions. 530: * 531: * @param obj the object to test against for equality 532: * @return true if the specified object is equal to this one 533: */ 534: public boolean equals(Object obj) 535: { 536: if (! (obj instanceof Rectangle2D)) 537: return false; 538: Rectangle2D r = (Rectangle2D) obj; 539: return r.getX() == getX() && r.getY() == getY() 540: && r.getWidth() == getWidth() && r.getHeight() == getHeight(); 541: } 542: 543: /** 544: * This class defines a rectangle in <code>double</code> precision. 545: * 546: * @author Eric Blake (ebb9@email.byu.edu) 547: * @since 1.2 548: * @status updated to 1.4 549: */ 550: public static class Double extends Rectangle2D 551: { 552: /** The x coordinate of the lower left corner. */ 553: public double x; 554: 555: /** The y coordinate of the lower left corner. */ 556: public double y; 557: 558: /** The width of the rectangle. */ 559: public double width; 560: 561: /** The height of the rectangle. */ 562: public double height; 563: 564: /** 565: * Create a rectangle at (0,0) with width 0 and height 0. 566: */ 567: public Double() 568: { 569: } 570: 571: /** 572: * Create a rectangle with the given values. 573: * 574: * @param x the x coordinate 575: * @param y the y coordinate 576: * @param w the width 577: * @param h the height 578: */ 579: public Double(double x, double y, double w, double h) 580: { 581: this.x = x; 582: this.y = y; 583: width = w; 584: height = h; 585: } 586: 587: /** 588: * Return the X coordinate. 589: * 590: * @return the value of x 591: */ 592: public double getX() 593: { 594: return x; 595: } 596: 597: /** 598: * Return the Y coordinate. 599: * 600: * @return the value of y 601: */ 602: public double getY() 603: { 604: return y; 605: } 606: 607: /** 608: * Return the width. 609: * 610: * @return the value of width 611: */ 612: public double getWidth() 613: { 614: return width; 615: } 616: 617: /** 618: * Return the height. 619: * 620: * @return the value of height 621: */ 622: public double getHeight() 623: { 624: return height; 625: } 626: 627: /** 628: * Test if the rectangle is empty. 629: * 630: * @return true if width or height is not positive 631: */ 632: public boolean isEmpty() 633: { 634: return width <= 0 || height <= 0; 635: } 636: 637: /** 638: * Set the contents of this rectangle to those specified. 639: * 640: * @param x the x coordinate 641: * @param y the y coordinate 642: * @param w the width 643: * @param h the height 644: */ 645: public void setRect(double x, double y, double w, double h) 646: { 647: this.x = x; 648: this.y = y; 649: width = w; 650: height = h; 651: } 652: 653: /** 654: * Set the contents of this rectangle to those specified. 655: * 656: * @param r the rectangle to copy 657: * @throws NullPointerException if r is null 658: */ 659: public void setRect(Rectangle2D r) 660: { 661: x = r.getX(); 662: y = r.getY(); 663: width = r.getWidth(); 664: height = r.getHeight(); 665: } 666: 667: /** 668: * Determine where the point lies with respect to this rectangle. The 669: * result will be the binary OR of the appropriate bit masks. 670: * 671: * @param x the x coordinate to check 672: * @param y the y coordinate to check 673: * @return the binary OR of the result 674: * @see #OUT_LEFT 675: * @see #OUT_TOP 676: * @see #OUT_RIGHT 677: * @see #OUT_BOTTOM 678: * @since 1.2 679: */ 680: public int outcode(double x, double y) 681: { 682: int result = 0; 683: if (width <= 0) 684: result |= OUT_LEFT | OUT_RIGHT; 685: else if (x < this.x) 686: result |= OUT_LEFT; 687: else if (x > this.x + width) 688: result |= OUT_RIGHT; 689: if (height <= 0) 690: result |= OUT_BOTTOM | OUT_TOP; 691: else if (y < this.y) // Remember that +y heads top-to-bottom. 692: result |= OUT_TOP; 693: else if (y > this.y + height) 694: result |= OUT_BOTTOM; 695: return result; 696: } 697: 698: /** 699: * Returns the bounds of this rectangle. A pretty useless method, as this 700: * is already a rectangle. 701: * 702: * @return a copy of this rectangle 703: */ 704: public Rectangle2D getBounds2D() 705: { 706: return new Double(x, y, width, height); 707: } 708: 709: /** 710: * Return a new rectangle which is the intersection of this and the given 711: * one. The result will be empty if there is no intersection. 712: * 713: * @param r the rectangle to be intersected 714: * @return the intersection 715: * @throws NullPointerException if r is null 716: */ 717: public Rectangle2D createIntersection(Rectangle2D r) 718: { 719: Double res = new Double(); 720: intersect(this, r, res); 721: return res; 722: } 723: 724: /** 725: * Return a new rectangle which is the union of this and the given one. 726: * 727: * @param r the rectangle to be merged 728: * @return the union 729: * @throws NullPointerException if r is null 730: */ 731: public Rectangle2D createUnion(Rectangle2D r) 732: { 733: Double res = new Double(); 734: union(this, r, res); 735: return res; 736: } 737: 738: /** 739: * Returns a string representation of this rectangle. This is in the form 740: * <code>getClass().getName() + "[x=" + x + ",y=" + y + ",w=" + width 741: * + ",h=" + height + ']'</code>. 742: * 743: * @return a string representation of this rectangle 744: */ 745: public String toString() 746: { 747: return getClass().getName() + "[x=" + x + ",y=" + y + ",w=" + width 748: + ",h=" + height + ']'; 749: } 750: } 751: 752: /** 753: * This class defines a rectangle in <code>float</code> precision. 754: * 755: * @author Eric Blake (ebb9@email.byu.edu) 756: * @since 1.2 757: * @status updated to 1.4 758: */ 759: public static class Float extends Rectangle2D 760: { 761: /** The x coordinate of the lower left corner. */ 762: public float x; 763: 764: /** The y coordinate of the lower left corner. */ 765: public float y; 766: 767: /** The width of the rectangle. */ 768: public float width; 769: 770: /** The height of the rectangle. */ 771: public float height; 772: 773: /** 774: * Create a rectangle at (0,0) with width 0 and height 0. 775: */ 776: public Float() 777: { 778: } 779: 780: /** 781: * Create a rectangle with the given values. 782: * 783: * @param x the x coordinate 784: * @param y the y coordinate 785: * @param w the width 786: * @param h the height 787: */ 788: public Float(float x, float y, float w, float h) 789: { 790: this.x = x; 791: this.y = y; 792: width = w; 793: height = h; 794: } 795: 796: /** 797: * Create a rectangle with the given values. 798: * 799: * @param x the x coordinate 800: * @param y the y coordinate 801: * @param w the width 802: * @param h the height 803: */ 804: Float(double x, double y, double w, double h) 805: { 806: this.x = (float) x; 807: this.y = (float) y; 808: width = (float) w; 809: height = (float) h; 810: } 811: 812: /** 813: * Return the X coordinate. 814: * 815: * @return the value of x 816: */ 817: public double getX() 818: { 819: return x; 820: } 821: 822: /** 823: * Return the Y coordinate. 824: * 825: * @return the value of y 826: */ 827: public double getY() 828: { 829: return y; 830: } 831: 832: /** 833: * Return the width. 834: * 835: * @return the value of width 836: */ 837: public double getWidth() 838: { 839: return width; 840: } 841: 842: /** 843: * Return the height. 844: * 845: * @return the value of height 846: */ 847: public double getHeight() 848: { 849: return height; 850: } 851: 852: /** 853: * Test if the rectangle is empty. 854: * 855: * @return true if width or height is not positive 856: */ 857: public boolean isEmpty() 858: { 859: return width <= 0 || height <= 0; 860: } 861: 862: /** 863: * Set the contents of this rectangle to those specified. 864: * 865: * @param x the x coordinate 866: * @param y the y coordinate 867: * @param w the width 868: * @param h the height 869: */ 870: public void setRect(float x, float y, float w, float h) 871: { 872: this.x = x; 873: this.y = y; 874: width = w; 875: height = h; 876: } 877: 878: /** 879: * Set the contents of this rectangle to those specified. 880: * 881: * @param x the x coordinate 882: * @param y the y coordinate 883: * @param w the width 884: * @param h the height 885: */ 886: public void setRect(double x, double y, double w, double h) 887: { 888: this.x = (float) x; 889: this.y = (float) y; 890: width = (float) w; 891: height = (float) h; 892: } 893: 894: /** 895: * Set the contents of this rectangle to those specified. 896: * 897: * @param r the rectangle to copy 898: * @throws NullPointerException if r is null 899: */ 900: public void setRect(Rectangle2D r) 901: { 902: x = (float) r.getX(); 903: y = (float) r.getY(); 904: width = (float) r.getWidth(); 905: height = (float) r.getHeight(); 906: } 907: 908: /** 909: * Determine where the point lies with respect to this rectangle. The 910: * result will be the binary OR of the appropriate bit masks. 911: * 912: * @param x the x coordinate to check 913: * @param y the y coordinate to check 914: * @return the binary OR of the result 915: * @see #OUT_LEFT 916: * @see #OUT_TOP 917: * @see #OUT_RIGHT 918: * @see #OUT_BOTTOM 919: * @since 1.2 920: */ 921: public int outcode(double x, double y) 922: { 923: int result = 0; 924: if (width <= 0) 925: result |= OUT_LEFT | OUT_RIGHT; 926: else if (x < this.x) 927: result |= OUT_LEFT; 928: else if (x > this.x + width) 929: result |= OUT_RIGHT; 930: if (height <= 0) 931: result |= OUT_BOTTOM | OUT_TOP; 932: else if (y < this.y) // Remember that +y heads top-to-bottom. 933: result |= OUT_TOP; 934: else if (y > this.y + height) 935: result |= OUT_BOTTOM; 936: return result; 937: } 938: 939: /** 940: * Returns the bounds of this rectangle. A pretty useless method, as this 941: * is already a rectangle. 942: * 943: * @return a copy of this rectangle 944: */ 945: public Rectangle2D getBounds2D() 946: { 947: return new Float(x, y, width, height); 948: } 949: 950: /** 951: * Return a new rectangle which is the intersection of this and the given 952: * one. The result will be empty if there is no intersection. 953: * 954: * @param r the rectangle to be intersected 955: * @return the intersection 956: * @throws NullPointerException if r is null 957: */ 958: public Rectangle2D createIntersection(Rectangle2D r) 959: { 960: Float res = new Float(); 961: intersect(this, r, res); 962: return res; 963: } 964: 965: /** 966: * Return a new rectangle which is the union of this and the given one. 967: * 968: * @param r the rectangle to be merged 969: * @return the union 970: * @throws NullPointerException if r is null 971: */ 972: public Rectangle2D createUnion(Rectangle2D r) 973: { 974: Float res = new Float(); 975: union(this, r, res); 976: return res; 977: } 978: 979: /** 980: * Returns a string representation of this rectangle. This is in the form 981: * <code>getClass().getName() + "[x=" + x + ",y=" + y + ",w=" + width 982: * + ",h=" + height + ']'</code>. 983: * 984: * @return a string representation of this rectangle 985: */ 986: public String toString() 987: { 988: return getClass().getName() + "[x=" + x + ",y=" + y + ",w=" + width 989: + ",h=" + height + ']'; 990: } 991: } 992: }