View Javadoc
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 }