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 
  26 package java.awt.geom;
  27 
  28 import java.io.Serializable;
  29 
  30 /**
  31  * The <code>Rectangle2D</code> 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  */
  43 public abstract class Rectangle2D extends RectangularShape {
  44     /**
  45      * The bitmask that indicates that a point lies to the left of
  46      * this <code>Rectangle2D</code>.
  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</code>.
  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</code>.
  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</code>.
  68      * @since 1.2
  69      */
  70     public static final int OUT_BOTTOM = 8;
  71 
  72     /**
  73      * The <code>Float</code> 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</code>.
  80          * @since 1.2
  81          * @serial
  82          */
  83         public float x;
  84 
  85         /**
  86          * The Y coordinate of this <code>Rectangle2D</code>.
  87          * @since 1.2
  88          * @serial
  89          */
  90         public float y;
  91 
  92         /**
  93          * The width of this <code>Rectangle2D</code>.
  94          * @since 1.2
  95          * @serial
  96          */
  97         public float width;
  98 
  99         /**
 100          * The height of this <code>Rectangle2D</code>.
 101          * @since 1.2
 102          * @serial
 103          */
 104         public float height;
 105 
 106         /**
 107          * Constructs a new <code>Rectangle2D</code>, initialized to
 108          * location (0.0,&nbsp;0.0) and size (0.0,&nbsp;0.0).
 109          * @since 1.2
 110          */
 111         public Float() {
 112         }
 113 
 114         /**
 115          * Constructs and initializes a <code>Rectangle2D</code>
 116          * from the specified <code>float</code> coordinates.
 117          *
 118          * @param x the X coordinate of the upper-left corner
 119          *          of the newly constructed <code>Rectangle2D</code>
 120          * @param y the Y coordinate of the upper-left corner
 121          *          of the newly constructed <code>Rectangle2D</code>
 122          * @param w the width of the newly constructed
 123          *          <code>Rectangle2D</code>
 124          * @param h the height of the newly constructed
 125          *          <code>Rectangle2D</code>
 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</code>
 174          * to the specified <code>float</code> values.
 175          *
 176          * @param x the X coordinate of the upper-left corner
 177          *          of this <code>Rectangle2D</code>
 178          * @param y the Y coordinate of the upper-left corner
 179          *          of this <code>Rectangle2D</code>
 180          * @param w the width of this <code>Rectangle2D</code>
 181          * @param h the height of this <code>Rectangle2D</code>
 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</code> representation of this
 286          * <code>Rectangle2D</code>.
 287          * @return a <code>String</code> representing this
 288          * <code>Rectangle2D</code>.
 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</code> 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</code>.
 313          * @since 1.2
 314          * @serial
 315          */
 316         public double x;
 317 
 318         /**
 319          * The Y coordinate of this <code>Rectangle2D</code>.
 320          * @since 1.2
 321          * @serial
 322          */
 323         public double y;
 324 
 325         /**
 326          * The width of this <code>Rectangle2D</code>.
 327          * @since 1.2
 328          * @serial
 329          */
 330         public double width;
 331 
 332         /**
 333          * The height of this <code>Rectangle2D</code>.
 334          * @since 1.2
 335          * @serial
 336          */
 337         public double height;
 338 
 339         /**
 340          * Constructs a new <code>Rectangle2D</code>, initialized to
 341          * location (0,&nbsp;0) and size (0,&nbsp;0).
 342          * @since 1.2
 343          */
 344         public Double() {
 345         }
 346 
 347         /**
 348          * Constructs and initializes a <code>Rectangle2D</code>
 349          * from the specified <code>double</code> coordinates.
 350          *
 351          * @param x the X coordinate of the upper-left corner
 352          *          of the newly constructed <code>Rectangle2D</code>
 353          * @param y the Y coordinate of the upper-left corner
 354          *          of the newly constructed <code>Rectangle2D</code>
 355          * @param w the width of the newly constructed
 356          *          <code>Rectangle2D</code>
 357          * @param h the height of the newly constructed
 358          *          <code>Rectangle2D</code>
 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</code> representation of this
 480          * <code>Rectangle2D</code>.
 481          * @return a <code>String</code> representing this
 482          * <code>Rectangle2D</code>.
 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</code>
 516      * to the specified <code>double</code> values.
 517      *
 518      * @param x the X coordinate of the upper-left corner
 519      *          of this <code>Rectangle2D</code>
 520      * @param y the Y coordinate of the upper-left corner
 521      *          of this <code>Rectangle2D</code>
 522      * @param w the width of this <code>Rectangle2D</code>
 523      * @param h the height of this <code>Rectangle2D</code>
 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</code> to be the same as the specified
 530      * <code>Rectangle2D</code>.
 531      * @param r the specified <code>Rectangle2D</code>
 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</code>.
 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</code> if the specified line segment intersects
 551      * the interior of this <code>Rectangle2D</code>; <code>false</code>
 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</code>.
 586      * @param l the specified {@link Line2D} to test for intersection
 587      * with the interior of this <code>Rectangle2D</code>
 588      * @return <code>true</code> if the specified <code>Line2D</code>
 589      * intersects the interior of this <code>Rectangle2D</code>;
 590      * <code>false</code> 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</code>.
 600      * This method computes a binary OR of the appropriate mask values
 601      * indicating, for each side of this <code>Rectangle2D</code>,
 602      * whether or not the specified coordinates are on the same side
 603      * of the edge as the rest of this <code>Rectangle2D</code>.
 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</code>.
 618      * This method computes a binary OR of the appropriate mask values
 619      * indicating, for each side of this <code>Rectangle2D</code>,
 620      * whether or not the specified <code>Point2D</code> is on the same
 621      * side of the edge as the rest of this <code>Rectangle2D</code>.
 622      * @param p the specified <code>Point2D</code>
 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</code> to the specified rectangular values.
 637      *
 638      * @param x the X coordinate of the upper-left corner
 639      *          of this <code>Rectangle2D</code>
 640      * @param y the Y coordinate of the upper-left corner
 641      *          of this <code>Rectangle2D</code>
 642      * @param w the width of this <code>Rectangle2D</code>
 643      * @param h the height of this <code>Rectangle2D</code>
 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</code> object representing the
 705      * intersection of this <code>Rectangle2D</code> with the specified
 706      * <code>Rectangle2D</code>.
 707      * @param r the <code>Rectangle2D</code> to be intersected with
 708      * this <code>Rectangle2D</code>
 709      * @return the largest <code>Rectangle2D</code> contained in both
 710      *          the specified <code>Rectangle2D</code> and in this
 711      *          <code>Rectangle2D</code>.
 712      * @since 1.2
 713      */
 714     public abstract Rectangle2D createIntersection(Rectangle2D r);
 715 
 716     /**
 717      * Intersects the pair of specified source <code>Rectangle2D</code>
 718      * objects and puts the result into the specified destination
 719      * <code>Rectangle2D</code> 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</code>
 724      * objects to be intersected with each other
 725      * @param src2 the second of a pair of <code>Rectangle2D</code>
 726      * objects to be intersected with each other
 727      * @param dest the <code>Rectangle2D</code> that holds the
 728      * results of the intersection of <code>src1</code> and
 729      * <code>src2</code>
 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</code> object representing the
 744      * union of this <code>Rectangle2D</code> with the specified
 745      * <code>Rectangle2D</code>.
 746      * @param r the <code>Rectangle2D</code> to be combined with
 747      * this <code>Rectangle2D</code>
 748      * @return the smallest <code>Rectangle2D</code> containing both
 749      * the specified <code>Rectangle2D</code> and this
 750      * <code>Rectangle2D</code>.
 751      * @since 1.2
 752      */
 753     public abstract Rectangle2D createUnion(Rectangle2D r);
 754 
 755     /**
 756      * Unions the pair of source <code>Rectangle2D</code> objects
 757      * and puts the result into the specified destination
 758      * <code>Rectangle2D</code> 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</code>
 763      * objects to be combined with each other
 764      * @param src2 the second of a pair of <code>Rectangle2D</code>
 765      * objects to be combined with each other
 766      * @param dest the <code>Rectangle2D</code> that holds the
 767      * results of the union of <code>src1</code> and
 768      * <code>src2</code>
 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</code> and <code>newy</code>, to this
 784      * <code>Rectangle2D</code>.  The resulting <code>Rectangle2D</code>
 785      * is the smallest <code>Rectangle2D</code> that
 786      * contains both the original <code>Rectangle2D</code> and the
 787      * specified point.
 788      * <p>
 789      * After adding a point, a call to <code>contains</code> with the
 790      * added point as an argument does not necessarily return
 791      * <code>true</code>. The <code>contains</code> method does not
 792      * return <code>true</code> 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</code> returns <code>false</code> 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</code> object <code>pt</code> to this
 810      * <code>Rectangle2D</code>.
 811      * The resulting <code>Rectangle2D</code> is the smallest
 812      * <code>Rectangle2D</code> that contains both the original
 813      * <code>Rectangle2D</code> and the specified <code>Point2D</code>.
 814      * <p>
 815      * After adding a point, a call to <code>contains</code> with the
 816      * added point as an argument does not necessarily return
 817      * <code>true</code>. The <code>contains</code>
 818      * method does not return <code>true</code> 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</code> returns <code>false</code> for that point.
 822      * @param     pt the new <code>Point2D</code> to add to this
 823      * <code>Rectangle2D</code>.
 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</code> object to this
 832      * <code>Rectangle2D</code>.  The resulting <code>Rectangle2D</code>
 833      * is the union of the two <code>Rectangle2D</code> objects.
 834      * @param r the <code>Rectangle2D</code> to add to this
 835      * <code>Rectangle2D</code>.
 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</code>.
 849      * The iterator for this class is multi-threaded safe, which means
 850      * that this <code>Rectangle2D</code> class guarantees that
 851      * modifications to the geometry of this <code>Rectangle2D</code>
 852      * object do not affect any iterations of that geometry that
 853      * are already in process.
 854      * @param at an optional <code>AffineTransform</code> to be applied to
 855      * the coordinates as they are returned in the iteration, or
 856      * <code>null</code> if untransformed coordinates are desired
 857      * @return    the <code>PathIterator</code> object that returns the
 858      *          geometry of the outline of this
 859      *          <code>Rectangle2D</code>, 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</code>.  Since rectangles are already
 869      * flat, the <code>flatness</code> parameter is ignored.
 870      * The iterator for this class is multi-threaded safe, which means
 871      * that this <code>Rectangle2D</code> class guarantees that
 872      * modifications to the geometry of this <code>Rectangle2D</code>
 873      * object do not affect any iterations of that geometry that
 874      * are already in process.
 875      * @param at an optional <code>AffineTransform</code> to be applied to
 876      * the coordinates as they are returned in the iteration, or
 877      * <code>null</code> 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</code> parameter is ignored.
 882      * @return    the <code>PathIterator</code> object that returns the
 883      *          geometry of the outline of this
 884      *          <code>Rectangle2D</code>, 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</code>.
 893      * @return the hashcode for this <code>Rectangle2D</code>.
 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</code> is
 906      * equal to this <code>Rectangle2D</code>.  The specified
 907      * <code>Object</code> is equal to this <code>Rectangle2D</code>
 908      * if it is an instance of <code>Rectangle2D</code> and if its
 909      * location and size are the same as this <code>Rectangle2D</code>.
 910      * @param obj an <code>Object</code> to be compared with this
 911      * <code>Rectangle2D</code>.
 912      * @return     <code>true</code> if <code>obj</code> is an instance
 913      *                     of <code>Rectangle2D</code> and has
 914      *                     the same values; <code>false</code> 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 }
--- EOF ---