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