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