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