1/* 2 * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package java.awt.geom; 27 28import java.io.Serializable; 29 30/** 31 * The {@code Rectangle2D} class describes a rectangle 32 * defined by a location {@code (x,y)} and dimension 33 * {@code (w x h)}. 34 * <p> 35 * This class is only the abstract superclass for all objects that 36 * store a 2D rectangle. 37 * The actual storage representation of the coordinates is left to 38 * the subclass. 39 * 40 * @author Jim Graham 41 * @since 1.2 42 */ 43public abstract class Rectangle2D extends RectangularShape { 44 /** 45 * The bitmask that indicates that a point lies to the left of 46 * this {@code Rectangle2D}. 47 * @since 1.2 48 */ 49 public static final int OUT_LEFT = 1; 50 51 /** 52 * The bitmask that indicates that a point lies above 53 * this {@code Rectangle2D}. 54 * @since 1.2 55 */ 56 public static final int OUT_TOP = 2; 57 58 /** 59 * The bitmask that indicates that a point lies to the right of 60 * this {@code Rectangle2D}. 61 * @since 1.2 62 */ 63 public static final int OUT_RIGHT = 4; 64 65 /** 66 * The bitmask that indicates that a point lies below 67 * this {@code Rectangle2D}. 68 * @since 1.2 69 */ 70 public static final int OUT_BOTTOM = 8; 71 72 /** 73 * The {@code Float} class defines a rectangle specified in float 74 * coordinates. 75 * @since 1.2 76 */ 77 public static class Float extends Rectangle2D implements Serializable { 78 /** 79 * The X coordinate of this {@code Rectangle2D}. 80 * @since 1.2 81 * @serial 82 */ 83 public float x; 84 85 /** 86 * The Y coordinate of this {@code Rectangle2D}. 87 * @since 1.2 88 * @serial 89 */ 90 public float y; 91 92 /** 93 * The width of this {@code Rectangle2D}. 94 * @since 1.2 95 * @serial 96 */ 97 public float width; 98 99 /** 100 * The height of this {@code Rectangle2D}. 101 * @since 1.2 102 * @serial 103 */ 104 public float height; 105 106 /** 107 * Constructs a new {@code Rectangle2D}, initialized to 108 * location (0.0, 0.0) and size (0.0, 0.0). 109 * @since 1.2 110 */ 111 public Float() { 112 } 113 114 /** 115 * Constructs and initializes a {@code Rectangle2D} 116 * from the specified {@code float} coordinates. 117 * 118 * @param x the X coordinate of the upper-left corner 119 * of the newly constructed {@code Rectangle2D} 120 * @param y the Y coordinate of the upper-left corner 121 * of the newly constructed {@code Rectangle2D} 122 * @param w the width of the newly constructed 123 * {@code Rectangle2D} 124 * @param h the height of the newly constructed 125 * {@code Rectangle2D} 126 * @since 1.2 127 */ 128 public Float(float x, float y, float w, float h) { 129 setRect(x, y, w, h); 130 } 131 132 /** 133 * {@inheritDoc} 134 * @since 1.2 135 */ 136 public double getX() { 137 return (double) x; 138 } 139 140 /** 141 * {@inheritDoc} 142 * @since 1.2 143 */ 144 public double getY() { 145 return (double) y; 146 } 147 148 /** 149 * {@inheritDoc} 150 * @since 1.2 151 */ 152 public double getWidth() { 153 return (double) width; 154 } 155 156 /** 157 * {@inheritDoc} 158 * @since 1.2 159 */ 160 public double getHeight() { 161 return (double) height; 162 } 163 164 /** 165 * {@inheritDoc} 166 * @since 1.2 167 */ 168 public boolean isEmpty() { 169 return (width <= 0.0f) || (height <= 0.0f); 170 } 171 172 /** 173 * Sets the location and size of this {@code Rectangle2D} 174 * to the specified {@code float} values. 175 * 176 * @param x the X coordinate of the upper-left corner 177 * of this {@code Rectangle2D} 178 * @param y the Y coordinate of the upper-left corner 179 * of this {@code Rectangle2D} 180 * @param w the width of this {@code Rectangle2D} 181 * @param h the height of this {@code Rectangle2D} 182 * @since 1.2 183 */ 184 public void setRect(float x, float y, float w, float h) { 185 this.x = x; 186 this.y = y; 187 this.width = w; 188 this.height = h; 189 } 190 191 /** 192 * {@inheritDoc} 193 * @since 1.2 194 */ 195 public void setRect(double x, double y, double w, double h) { 196 this.x = (float) x; 197 this.y = (float) y; 198 this.width = (float) w; 199 this.height = (float) h; 200 } 201 202 /** 203 * {@inheritDoc} 204 * @since 1.2 205 */ 206 public void setRect(Rectangle2D r) { 207 this.x = (float) r.getX(); 208 this.y = (float) r.getY(); 209 this.width = (float) r.getWidth(); 210 this.height = (float) r.getHeight(); 211 } 212 213 /** 214 * {@inheritDoc} 215 * @since 1.2 216 */ 217 public int outcode(double x, double y) { 218 /* 219 * Note on casts to double below. If the arithmetic of 220 * x+w or y+h is done in float, then some bits may be 221 * lost if the binary exponents of x/y and w/h are not 222 * similar. By converting to double before the addition 223 * we force the addition to be carried out in double to 224 * avoid rounding error in the comparison. 225 * 226 * See bug 4320890 for problems that this inaccuracy causes. 227 */ 228 int out = 0; 229 if (this.width <= 0) { 230 out |= OUT_LEFT | OUT_RIGHT; 231 } else if (x < this.x) { 232 out |= OUT_LEFT; 233 } else if (x > this.x + (double) this.width) { 234 out |= OUT_RIGHT; 235 } 236 if (this.height <= 0) { 237 out |= OUT_TOP | OUT_BOTTOM; 238 } else if (y < this.y) { 239 out |= OUT_TOP; 240 } else if (y > this.y + (double) this.height) { 241 out |= OUT_BOTTOM; 242 } 243 return out; 244 } 245 246 /** 247 * {@inheritDoc} 248 * @since 1.2 249 */ 250 public Rectangle2D getBounds2D() { 251 return new Float(x, y, width, height); 252 } 253 254 /** 255 * {@inheritDoc} 256 * @since 1.2 257 */ 258 public Rectangle2D createIntersection(Rectangle2D r) { 259 Rectangle2D dest; 260 if (r instanceof Float) { 261 dest = new Rectangle2D.Float(); 262 } else { 263 dest = new Rectangle2D.Double(); 264 } 265 Rectangle2D.intersect(this, r, dest); 266 return dest; 267 } 268 269 /** 270 * {@inheritDoc} 271 * @since 1.2 272 */ 273 public Rectangle2D createUnion(Rectangle2D r) { 274 Rectangle2D dest; 275 if (r instanceof Float) { 276 dest = new Rectangle2D.Float(); 277 } else { 278 dest = new Rectangle2D.Double(); 279 } 280 Rectangle2D.union(this, r, dest); 281 return dest; 282 } 283 284 /** 285 * Returns the {@code String} representation of this 286 * {@code Rectangle2D}. 287 * @return a {@code String} representing this 288 * {@code Rectangle2D}. 289 * @since 1.2 290 */ 291 public String toString() { 292 return getClass().getName() 293 + "[x=" + x + 294 ",y=" + y + 295 ",w=" + width + 296 ",h=" + height + "]"; 297 } 298 299 /* 300 * JDK 1.6 serialVersionUID 301 */ 302 private static final long serialVersionUID = 3798716824173675777L; 303 } 304 305 /** 306 * The {@code Double} class defines a rectangle specified in 307 * double coordinates. 308 * @since 1.2 309 */ 310 public static class Double extends Rectangle2D implements Serializable { 311 /** 312 * The X coordinate of this {@code Rectangle2D}. 313 * @since 1.2 314 * @serial 315 */ 316 public double x; 317 318 /** 319 * The Y coordinate of this {@code Rectangle2D}. 320 * @since 1.2 321 * @serial 322 */ 323 public double y; 324 325 /** 326 * The width of this {@code Rectangle2D}. 327 * @since 1.2 328 * @serial 329 */ 330 public double width; 331 332 /** 333 * The height of this {@code Rectangle2D}. 334 * @since 1.2 335 * @serial 336 */ 337 public double height; 338 339 /** 340 * Constructs a new {@code Rectangle2D}, initialized to 341 * location (0, 0) and size (0, 0). 342 * @since 1.2 343 */ 344 public Double() { 345 } 346 347 /** 348 * Constructs and initializes a {@code Rectangle2D} 349 * from the specified {@code double} coordinates. 350 * 351 * @param x the X coordinate of the upper-left corner 352 * of the newly constructed {@code Rectangle2D} 353 * @param y the Y coordinate of the upper-left corner 354 * of the newly constructed {@code Rectangle2D} 355 * @param w the width of the newly constructed 356 * {@code Rectangle2D} 357 * @param h the height of the newly constructed 358 * {@code Rectangle2D} 359 * @since 1.2 360 */ 361 public Double(double x, double y, double w, double h) { 362 setRect(x, y, w, h); 363 } 364 365 /** 366 * {@inheritDoc} 367 * @since 1.2 368 */ 369 public double getX() { 370 return x; 371 } 372 373 /** 374 * {@inheritDoc} 375 * @since 1.2 376 */ 377 public double getY() { 378 return y; 379 } 380 381 /** 382 * {@inheritDoc} 383 * @since 1.2 384 */ 385 public double getWidth() { 386 return width; 387 } 388 389 /** 390 * {@inheritDoc} 391 * @since 1.2 392 */ 393 public double getHeight() { 394 return height; 395 } 396 397 /** 398 * {@inheritDoc} 399 * @since 1.2 400 */ 401 public boolean isEmpty() { 402 return (width <= 0.0) || (height <= 0.0); 403 } 404 405 /** 406 * {@inheritDoc} 407 * @since 1.2 408 */ 409 public void setRect(double x, double y, double w, double h) { 410 this.x = x; 411 this.y = y; 412 this.width = w; 413 this.height = h; 414 } 415 416 /** 417 * {@inheritDoc} 418 * @since 1.2 419 */ 420 public void setRect(Rectangle2D r) { 421 this.x = r.getX(); 422 this.y = r.getY(); 423 this.width = r.getWidth(); 424 this.height = r.getHeight(); 425 } 426 427 /** 428 * {@inheritDoc} 429 * @since 1.2 430 */ 431 public int outcode(double x, double y) { 432 int out = 0; 433 if (this.width <= 0) { 434 out |= OUT_LEFT | OUT_RIGHT; 435 } else if (x < this.x) { 436 out |= OUT_LEFT; 437 } else if (x > this.x + this.width) { 438 out |= OUT_RIGHT; 439 } 440 if (this.height <= 0) { 441 out |= OUT_TOP | OUT_BOTTOM; 442 } else if (y < this.y) { 443 out |= OUT_TOP; 444 } else if (y > this.y + this.height) { 445 out |= OUT_BOTTOM; 446 } 447 return out; 448 } 449 450 /** 451 * {@inheritDoc} 452 * @since 1.2 453 */ 454 public Rectangle2D getBounds2D() { 455 return new Double(x, y, width, height); 456 } 457 458 /** 459 * {@inheritDoc} 460 * @since 1.2 461 */ 462 public Rectangle2D createIntersection(Rectangle2D r) { 463 Rectangle2D dest = new Rectangle2D.Double(); 464 Rectangle2D.intersect(this, r, dest); 465 return dest; 466 } 467 468 /** 469 * {@inheritDoc} 470 * @since 1.2 471 */ 472 public Rectangle2D createUnion(Rectangle2D r) { 473 Rectangle2D dest = new Rectangle2D.Double(); 474 Rectangle2D.union(this, r, dest); 475 return dest; 476 } 477 478 /** 479 * Returns the {@code String} representation of this 480 * {@code Rectangle2D}. 481 * @return a {@code String} representing this 482 * {@code Rectangle2D}. 483 * @since 1.2 484 */ 485 public String toString() { 486 return getClass().getName() 487 + "[x=" + x + 488 ",y=" + y + 489 ",w=" + width + 490 ",h=" + height + "]"; 491 } 492 493 /* 494 * JDK 1.6 serialVersionUID 495 */ 496 private static final long serialVersionUID = 7771313791441850493L; 497 } 498 499 /** 500 * This is an abstract class that cannot be instantiated directly. 501 * Type-specific implementation subclasses are available for 502 * instantiation and provide a number of formats for storing 503 * the information necessary to satisfy the various accessor 504 * methods below. 505 * 506 * @see java.awt.geom.Rectangle2D.Float 507 * @see java.awt.geom.Rectangle2D.Double 508 * @see java.awt.Rectangle 509 * @since 1.2 510 */ 511 protected Rectangle2D() { 512 } 513 514 /** 515 * Sets the location and size of this {@code Rectangle2D} 516 * to the specified {@code double} values. 517 * 518 * @param x the X coordinate of the upper-left corner 519 * of this {@code Rectangle2D} 520 * @param y the Y coordinate of the upper-left corner 521 * of this {@code Rectangle2D} 522 * @param w the width of this {@code Rectangle2D} 523 * @param h the height of this {@code Rectangle2D} 524 * @since 1.2 525 */ 526 public abstract void setRect(double x, double y, double w, double h); 527 528 /** 529 * Sets this {@code Rectangle2D} to be the same as the specified 530 * {@code Rectangle2D}. 531 * @param r the specified {@code Rectangle2D} 532 * @since 1.2 533 */ 534 public void setRect(Rectangle2D r) { 535 setRect(r.getX(), r.getY(), r.getWidth(), r.getHeight()); 536 } 537 538 /** 539 * Tests if the specified line segment intersects the interior of this 540 * {@code Rectangle2D}. 541 * 542 * @param x1 the X coordinate of the start point of the specified 543 * line segment 544 * @param y1 the Y coordinate of the start point of the specified 545 * line segment 546 * @param x2 the X coordinate of the end point of the specified 547 * line segment 548 * @param y2 the Y coordinate of the end point of the specified 549 * line segment 550 * @return {@code true} if the specified line segment intersects 551 * the interior of this {@code Rectangle2D}; {@code false} 552 * otherwise. 553 * @since 1.2 554 */ 555 public boolean intersectsLine(double x1, double y1, double x2, double y2) { 556 int out1, out2; 557 if ((out2 = outcode(x2, y2)) == 0) { 558 return true; 559 } 560 while ((out1 = outcode(x1, y1)) != 0) { 561 if ((out1 & out2) != 0) { 562 return false; 563 } 564 if ((out1 & (OUT_LEFT | OUT_RIGHT)) != 0) { 565 double x = getX(); 566 if ((out1 & OUT_RIGHT) != 0) { 567 x += getWidth(); 568 } 569 y1 = y1 + (x - x1) * (y2 - y1) / (x2 - x1); 570 x1 = x; 571 } else { 572 double y = getY(); 573 if ((out1 & OUT_BOTTOM) != 0) { 574 y += getHeight(); 575 } 576 x1 = x1 + (y - y1) * (x2 - x1) / (y2 - y1); 577 y1 = y; 578 } 579 } 580 return true; 581 } 582 583 /** 584 * Tests if the specified line segment intersects the interior of this 585 * {@code Rectangle2D}. 586 * @param l the specified {@link Line2D} to test for intersection 587 * with the interior of this {@code Rectangle2D} 588 * @return {@code true} if the specified {@code Line2D} 589 * intersects the interior of this {@code Rectangle2D}; 590 * {@code false} otherwise. 591 * @since 1.2 592 */ 593 public boolean intersectsLine(Line2D l) { 594 return intersectsLine(l.getX1(), l.getY1(), l.getX2(), l.getY2()); 595 } 596 597 /** 598 * Determines where the specified coordinates lie with respect 599 * to this {@code Rectangle2D}. 600 * This method computes a binary OR of the appropriate mask values 601 * indicating, for each side of this {@code Rectangle2D}, 602 * whether or not the specified coordinates are on the same side 603 * of the edge as the rest of this {@code Rectangle2D}. 604 * @param x the specified X coordinate 605 * @param y the specified Y coordinate 606 * @return the logical OR of all appropriate out codes. 607 * @see #OUT_LEFT 608 * @see #OUT_TOP 609 * @see #OUT_RIGHT 610 * @see #OUT_BOTTOM 611 * @since 1.2 612 */ 613 public abstract int outcode(double x, double y); 614 615 /** 616 * Determines where the specified {@link Point2D} lies with 617 * respect to this {@code Rectangle2D}. 618 * This method computes a binary OR of the appropriate mask values 619 * indicating, for each side of this {@code Rectangle2D}, 620 * whether or not the specified {@code Point2D} is on the same 621 * side of the edge as the rest of this {@code Rectangle2D}. 622 * @param p the specified {@code Point2D} 623 * @return the logical OR of all appropriate out codes. 624 * @see #OUT_LEFT 625 * @see #OUT_TOP 626 * @see #OUT_RIGHT 627 * @see #OUT_BOTTOM 628 * @since 1.2 629 */ 630 public int outcode(Point2D p) { 631 return outcode(p.getX(), p.getY()); 632 } 633 634 /** 635 * Sets the location and size of the outer bounds of this 636 * {@code Rectangle2D} to the specified rectangular values. 637 * 638 * @param x the X coordinate of the upper-left corner 639 * of this {@code Rectangle2D} 640 * @param y the Y coordinate of the upper-left corner 641 * of this {@code Rectangle2D} 642 * @param w the width of this {@code Rectangle2D} 643 * @param h the height of this {@code Rectangle2D} 644 * @since 1.2 645 */ 646 public void setFrame(double x, double y, double w, double h) { 647 setRect(x, y, w, h); 648 } 649 650 /** 651 * {@inheritDoc} 652 * @since 1.2 653 */ 654 public Rectangle2D getBounds2D() { 655 return (Rectangle2D) clone(); 656 } 657 658 /** 659 * {@inheritDoc} 660 * @since 1.2 661 */ 662 public boolean contains(double x, double y) { 663 double x0 = getX(); 664 double y0 = getY(); 665 return (x >= x0 && 666 y >= y0 && 667 x < x0 + getWidth() && 668 y < y0 + getHeight()); 669 } 670 671 /** 672 * {@inheritDoc} 673 * @since 1.2 674 */ 675 public boolean intersects(double x, double y, double w, double h) { 676 if (isEmpty() || w <= 0 || h <= 0) { 677 return false; 678 } 679 double x0 = getX(); 680 double y0 = getY(); 681 return (x + w > x0 && 682 y + h > y0 && 683 x < x0 + getWidth() && 684 y < y0 + getHeight()); 685 } 686 687 /** 688 * {@inheritDoc} 689 * @since 1.2 690 */ 691 public boolean contains(double x, double y, double w, double h) { 692 if (isEmpty() || w <= 0 || h <= 0) { 693 return false; 694 } 695 double x0 = getX(); 696 double y0 = getY(); 697 return (x >= x0 && 698 y >= y0 && 699 (x + w) <= x0 + getWidth() && 700 (y + h) <= y0 + getHeight()); 701 } 702 703 /** 704 * Returns a new {@code Rectangle2D} object representing the 705 * intersection of this {@code Rectangle2D} with the specified 706 * {@code Rectangle2D}. 707 * @param r the {@code Rectangle2D} to be intersected with 708 * this {@code Rectangle2D} 709 * @return the largest {@code Rectangle2D} contained in both 710 * the specified {@code Rectangle2D} and in this 711 * {@code Rectangle2D}. 712 * @since 1.2 713 */ 714 public abstract Rectangle2D createIntersection(Rectangle2D r); 715 716 /** 717 * Intersects the pair of specified source {@code Rectangle2D} 718 * objects and puts the result into the specified destination 719 * {@code Rectangle2D} object. One of the source rectangles 720 * can also be the destination to avoid creating a third Rectangle2D 721 * object, but in this case the original points of this source 722 * rectangle will be overwritten by this method. 723 * @param src1 the first of a pair of {@code Rectangle2D} 724 * objects to be intersected with each other 725 * @param src2 the second of a pair of {@code Rectangle2D} 726 * objects to be intersected with each other 727 * @param dest the {@code Rectangle2D} that holds the 728 * results of the intersection of {@code src1} and 729 * {@code src2} 730 * @since 1.2 731 */ 732 public static void intersect(Rectangle2D src1, 733 Rectangle2D src2, 734 Rectangle2D dest) { 735 double x1 = Math.max(src1.getMinX(), src2.getMinX()); 736 double y1 = Math.max(src1.getMinY(), src2.getMinY()); 737 double x2 = Math.min(src1.getMaxX(), src2.getMaxX()); 738 double y2 = Math.min(src1.getMaxY(), src2.getMaxY()); 739 dest.setFrame(x1, y1, x2-x1, y2-y1); 740 } 741 742 /** 743 * Returns a new {@code Rectangle2D} object representing the 744 * union of this {@code Rectangle2D} with the specified 745 * {@code Rectangle2D}. 746 * @param r the {@code Rectangle2D} to be combined with 747 * this {@code Rectangle2D} 748 * @return the smallest {@code Rectangle2D} containing both 749 * the specified {@code Rectangle2D} and this 750 * {@code Rectangle2D}. 751 * @since 1.2 752 */ 753 public abstract Rectangle2D createUnion(Rectangle2D r); 754 755 /** 756 * Unions the pair of source {@code Rectangle2D} objects 757 * and puts the result into the specified destination 758 * {@code Rectangle2D} object. One of the source rectangles 759 * can also be the destination to avoid creating a third Rectangle2D 760 * object, but in this case the original points of this source 761 * rectangle will be overwritten by this method. 762 * @param src1 the first of a pair of {@code Rectangle2D} 763 * objects to be combined with each other 764 * @param src2 the second of a pair of {@code Rectangle2D} 765 * objects to be combined with each other 766 * @param dest the {@code Rectangle2D} that holds the 767 * results of the union of {@code src1} and 768 * {@code src2} 769 * @since 1.2 770 */ 771 public static void union(Rectangle2D src1, 772 Rectangle2D src2, 773 Rectangle2D dest) { 774 double x1 = Math.min(src1.getMinX(), src2.getMinX()); 775 double y1 = Math.min(src1.getMinY(), src2.getMinY()); 776 double x2 = Math.max(src1.getMaxX(), src2.getMaxX()); 777 double y2 = Math.max(src1.getMaxY(), src2.getMaxY()); 778 dest.setFrameFromDiagonal(x1, y1, x2, y2); 779 } 780 781 /** 782 * Adds a point, specified by the double precision arguments 783 * {@code newx} and {@code newy}, to this 784 * {@code Rectangle2D}. The resulting {@code Rectangle2D} 785 * is the smallest {@code Rectangle2D} that 786 * contains both the original {@code Rectangle2D} and the 787 * specified point. 788 * <p> 789 * After adding a point, a call to {@code contains} with the 790 * added point as an argument does not necessarily return 791 * {@code true}. The {@code contains} method does not 792 * return {@code true} for points on the right or bottom 793 * edges of a rectangle. Therefore, if the added point falls on 794 * the left or bottom edge of the enlarged rectangle, 795 * {@code contains} returns {@code false} for that point. 796 * @param newx the X coordinate of the new point 797 * @param newy the Y coordinate of the new point 798 * @since 1.2 799 */ 800 public void add(double newx, double newy) { 801 double x1 = Math.min(getMinX(), newx); 802 double x2 = Math.max(getMaxX(), newx); 803 double y1 = Math.min(getMinY(), newy); 804 double y2 = Math.max(getMaxY(), newy); 805 setRect(x1, y1, x2 - x1, y2 - y1); 806 } 807 808 /** 809 * Adds the {@code Point2D} object {@code pt} to this 810 * {@code Rectangle2D}. 811 * The resulting {@code Rectangle2D} is the smallest 812 * {@code Rectangle2D} that contains both the original 813 * {@code Rectangle2D} and the specified {@code Point2D}. 814 * <p> 815 * After adding a point, a call to {@code contains} with the 816 * added point as an argument does not necessarily return 817 * {@code true}. The {@code contains} 818 * method does not return {@code true} for points on the right 819 * or bottom edges of a rectangle. Therefore, if the added point falls 820 * on the left or bottom edge of the enlarged rectangle, 821 * {@code contains} returns {@code false} for that point. 822 * @param pt the new {@code Point2D} to add to this 823 * {@code Rectangle2D}. 824 * @since 1.2 825 */ 826 public void add(Point2D pt) { 827 add(pt.getX(), pt.getY()); 828 } 829 830 /** 831 * Adds a {@code Rectangle2D} object to this 832 * {@code Rectangle2D}. The resulting {@code Rectangle2D} 833 * is the union of the two {@code Rectangle2D} objects. 834 * @param r the {@code Rectangle2D} to add to this 835 * {@code Rectangle2D}. 836 * @since 1.2 837 */ 838 public void add(Rectangle2D r) { 839 double x1 = Math.min(getMinX(), r.getMinX()); 840 double x2 = Math.max(getMaxX(), r.getMaxX()); 841 double y1 = Math.min(getMinY(), r.getMinY()); 842 double y2 = Math.max(getMaxY(), r.getMaxY()); 843 setRect(x1, y1, x2 - x1, y2 - y1); 844 } 845 846 /** 847 * Returns an iteration object that defines the boundary of this 848 * {@code Rectangle2D}. 849 * The iterator for this class is multi-threaded safe, which means 850 * that this {@code Rectangle2D} class guarantees that 851 * modifications to the geometry of this {@code Rectangle2D} 852 * object do not affect any iterations of that geometry that 853 * are already in process. 854 * @param at an optional {@code AffineTransform} to be applied to 855 * the coordinates as they are returned in the iteration, or 856 * {@code null} if untransformed coordinates are desired 857 * @return the {@code PathIterator} object that returns the 858 * geometry of the outline of this 859 * {@code Rectangle2D}, one segment at a time. 860 * @since 1.2 861 */ 862 public PathIterator getPathIterator(AffineTransform at) { 863 return new RectIterator(this, at); 864 } 865 866 /** 867 * Returns an iteration object that defines the boundary of the 868 * flattened {@code Rectangle2D}. Since rectangles are already 869 * flat, the {@code flatness} parameter is ignored. 870 * The iterator for this class is multi-threaded safe, which means 871 * that this {@code Rectangle2D} class guarantees that 872 * modifications to the geometry of this {@code Rectangle2D} 873 * object do not affect any iterations of that geometry that 874 * are already in process. 875 * @param at an optional {@code AffineTransform} to be applied to 876 * the coordinates as they are returned in the iteration, or 877 * {@code null} if untransformed coordinates are desired 878 * @param flatness the maximum distance that the line segments used to 879 * approximate the curved segments are allowed to deviate from any 880 * point on the original curve. Since rectangles are already flat, 881 * the {@code flatness} parameter is ignored. 882 * @return the {@code PathIterator} object that returns the 883 * geometry of the outline of this 884 * {@code Rectangle2D}, one segment at a time. 885 * @since 1.2 886 */ 887 public PathIterator getPathIterator(AffineTransform at, double flatness) { 888 return new RectIterator(this, at); 889 } 890 891 /** 892 * Returns the hashcode for this {@code Rectangle2D}. 893 * @return the hashcode for this {@code Rectangle2D}. 894 * @since 1.2 895 */ 896 public int hashCode() { 897 long bits = java.lang.Double.doubleToLongBits(getX()); 898 bits += java.lang.Double.doubleToLongBits(getY()) * 37; 899 bits += java.lang.Double.doubleToLongBits(getWidth()) * 43; 900 bits += java.lang.Double.doubleToLongBits(getHeight()) * 47; 901 return (((int) bits) ^ ((int) (bits >> 32))); 902 } 903 904 /** 905 * Determines whether or not the specified {@code Object} is 906 * equal to this {@code Rectangle2D}. The specified 907 * {@code Object} is equal to this {@code Rectangle2D} 908 * if it is an instance of {@code Rectangle2D} and if its 909 * location and size are the same as this {@code Rectangle2D}. 910 * @param obj an {@code Object} to be compared with this 911 * {@code Rectangle2D}. 912 * @return {@code true} if {@code obj} is an instance 913 * of {@code Rectangle2D} and has 914 * the same values; {@code false} otherwise. 915 * @since 1.2 916 */ 917 public boolean equals(Object obj) { 918 if (obj == this) { 919 return true; 920 } 921 if (obj instanceof Rectangle2D) { 922 Rectangle2D r2d = (Rectangle2D) obj; 923 return ((getX() == r2d.getX()) && 924 (getY() == r2d.getY()) && 925 (getWidth() == r2d.getWidth()) && 926 (getHeight() == r2d.getHeight())); 927 } 928 return false; 929 } 930} 931