1 /* Rectangle2D.java -- generic rectangles in 2-D space 2 Copyright (C) 2000, 2001, 2002 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., 59 Temple Place, Suite 330, Boston, MA 19 02111-1307 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() 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() 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() 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() 84 */ 85 public static final int OUT_BOTTOM = 8; 86 87 /** 88 * Default constructor. 89 */ Rectangle2D()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 */ setRect(double x, double y, double w, double h)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 */ setRect(Rectangle2D r)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 */ intersectsLine(double x1, double y1, double x2, double y2)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 */ intersectsLine(Line2D l)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 */ outcode(double x, double y)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 */ outcode(Point2D p)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 */ setFrame(double x, double y, double w, double h)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 */ getBounds2D()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 */ contains(double x, double y)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 */ intersects(double x, double y, double w, double h)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 */ contains(double x, double y, double w, double h)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 */ createIntersection(Rectangle2D r)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 */ intersect(Rectangle2D src1, Rectangle2D src2, Rectangle2D dest)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 */ createUnion(Rectangle2D r)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 */ union(Rectangle2D src1, Rectangle2D src2, Rectangle2D dest)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 x the X coordinate of the point to add to this rectangle 339 * @param y the Y coordinate of the point to add to this rectangle 340 */ add(double newx, double newy)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 */ add(Point2D p)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) 372 */ add(Rectangle2D r)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 transform an optional transform to apply to the iterator 386 * @return a new iterator over the boundary 387 * @since 1.2 388 */ getPathIterator(final AffineTransform at)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 transform an optional transform to apply to the iterator 494 * @param double the maximum distance for deviation from the real boundary 495 * @return a new iterator over the boundary 496 * @since 1.2 497 */ getPathIterator(AffineTransform at, double flatness)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 */ hashCode()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 */ equals(Object obj)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 */ Double()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 */ Double(double x, double y, double w, double h)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 */ getX()592 public double getX() 593 { 594 return x; 595 } 596 597 /** 598 * Return the Y coordinate. 599 * 600 * @return the value of y 601 */ getY()602 public double getY() 603 { 604 return y; 605 } 606 607 /** 608 * Return the width. 609 * 610 * @return the value of width 611 */ getWidth()612 public double getWidth() 613 { 614 return width; 615 } 616 617 /** 618 * Return the height. 619 * 620 * @return the value of height 621 */ getHeight()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 */ isEmpty()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 */ setRect(double x, double y, double w, double h)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 */ setRect(Rectangle2D r)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 */ outcode(double x, double y)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 */ getBounds2D()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 */ createIntersection(Rectangle2D r)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 */ createUnion(Rectangle2D r)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 */ toString()745 public String toString() 746 { 747 return getClass().getName() + "[x=" + x + ",y=" + y + ",w=" + width 748 + ",h=" + height + ']'; 749 } 750 } // class Double 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 */ Float()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 */ Float(float x, float y, float w, float h)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 */ Float(double x, double y, double w, double h)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 */ getX()817 public double getX() 818 { 819 return x; 820 } 821 822 /** 823 * Return the Y coordinate. 824 * 825 * @return the value of y 826 */ getY()827 public double getY() 828 { 829 return y; 830 } 831 832 /** 833 * Return the width. 834 * 835 * @return the value of width 836 */ getWidth()837 public double getWidth() 838 { 839 return width; 840 } 841 842 /** 843 * Return the height. 844 * 845 * @return the value of height 846 */ getHeight()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 */ isEmpty()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 */ setRect(float x, float y, float w, float h)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 */ setRect(double x, double y, double w, double h)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 */ setRect(Rectangle2D r)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 */ outcode(double x, double y)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 */ getBounds2D()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 */ createIntersection(Rectangle2D r)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 */ createUnion(Rectangle2D r)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 */ toString()986 public String toString() 987 { 988 return getClass().getName() + "[x=" + x + ",y=" + y + ",w=" + width 989 + ",h=" + height + ']'; 990 } 991 } // class Float 992 } // class Rectangle2D 993