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} 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}.
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,&nbsp;0.0) and size (0.0,&nbsp;0.0).
109          * @since 1.2
110          */
Float()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         */
Float(float x, float y, float w, float h)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          */
getX()136         public double getX() {
137             return (double) x;
138         }
139 
140         /**
141          * {@inheritDoc}
142          * @since 1.2
143          */
getY()144         public double getY() {
145             return (double) y;
146         }
147 
148         /**
149          * {@inheritDoc}
150          * @since 1.2
151          */
getWidth()152         public double getWidth() {
153             return (double) width;
154         }
155 
156         /**
157          * {@inheritDoc}
158          * @since 1.2
159          */
getHeight()160         public double getHeight() {
161             return (double) height;
162         }
163 
164         /**
165          * {@inheritDoc}
166          * @since 1.2
167          */
isEmpty()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          */
setRect(float x, float y, float w, float h)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          */
setRect(double x, double y, double w, double h)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          */
setRect(Rectangle2D r)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          */
outcode(double x, double y)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          */
getBounds2D()250         public Rectangle2D getBounds2D() {
251             return new Float(x, y, width, height);
252         }
253 
254         /**
255          * {@inheritDoc}
256          * @since 1.2
257          */
createIntersection(Rectangle2D r)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          */
createUnion(Rectangle2D r)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          */
toString()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,&nbsp;0) and size (0,&nbsp;0).
342          * @since 1.2
343          */
Double()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          */
Double(double x, double y, double w, double h)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          */
getX()369         public double getX() {
370             return x;
371         }
372 
373         /**
374          * {@inheritDoc}
375          * @since 1.2
376          */
getY()377         public double getY() {
378             return y;
379         }
380 
381         /**
382          * {@inheritDoc}
383          * @since 1.2
384          */
getWidth()385         public double getWidth() {
386             return width;
387         }
388 
389         /**
390          * {@inheritDoc}
391          * @since 1.2
392          */
getHeight()393         public double getHeight() {
394             return height;
395         }
396 
397         /**
398          * {@inheritDoc}
399          * @since 1.2
400          */
isEmpty()401         public boolean isEmpty() {
402             return (width <= 0.0) || (height <= 0.0);
403         }
404 
405         /**
406          * {@inheritDoc}
407          * @since 1.2
408          */
setRect(double x, double y, double w, double h)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          */
setRect(Rectangle2D r)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          */
outcode(double x, double y)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          */
getBounds2D()454         public Rectangle2D getBounds2D() {
455             return new Double(x, y, width, height);
456         }
457 
458         /**
459          * {@inheritDoc}
460          * @since 1.2
461          */
createIntersection(Rectangle2D r)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          */
createUnion(Rectangle2D r)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          */
toString()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      */
Rectangle2D()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      */
setRect(double x, double y, double w, double h)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      */
setRect(Rectangle2D r)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      */
intersectsLine(double x1, double y1, double x2, double y2)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      */
intersectsLine(Line2D l)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      */
outcode(double x, double y)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      */
outcode(Point2D p)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      */
setFrame(double x, double y, double w, double h)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      */
getBounds2D()654     public Rectangle2D getBounds2D() {
655         return (Rectangle2D) clone();
656     }
657 
658     /**
659      * {@inheritDoc}
660      * @since 1.2
661      */
contains(double x, double y)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      */
intersects(double x, double y, double w, double h)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      */
contains(double x, double y, double w, double h)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      */
createIntersection(Rectangle2D r)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      */
intersect(Rectangle2D src1, Rectangle2D src2, Rectangle2D dest)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      */
createUnion(Rectangle2D r)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      */
union(Rectangle2D src1, Rectangle2D src2, Rectangle2D dest)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      */
add(double newx, double newy)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      */
add(Point2D pt)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      */
add(Rectangle2D r)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      */
getPathIterator(AffineTransform at)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      */
getPathIterator(AffineTransform at, double flatness)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      */
hashCode()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      */
equals(Object obj)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