comparison dwtx/draw2d/geometry/Rectangle.d @ 98:95307ad235d9

Added Draw2d code, still work in progress
author Frank Benoit <benoit@tionex.de>
date Sun, 03 Aug 2008 00:52:14 +0200
parents
children 1082a0fc2bb8
comparison
equal deleted inserted replaced
96:b492ba44e44d 98:95307ad235d9
1 /*******************************************************************************
2 * Copyright (c) 2000, 2008 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * IBM Corporation - initial API and implementation
10 * Port to the D programming language:
11 * Frank Benoit <benoit@tionex.de>
12 *******************************************************************************/
13 module dwtx.draw2d.geometry.Rectangle;
14
15 import dwt.dwthelper.utils;
16
17 import dwtx.draw2d.geometry.Translatable;
18 import dwtx.draw2d.geometry.Point;
19 import dwtx.draw2d.geometry.Dimension;
20 import dwtx.draw2d.geometry.Insets;
21 import dwtx.draw2d.PositionConstants;
22 import tango.text.convert.Format;
23
24 static import dwt.graphics.Rectangle;
25
26 /**
27 * Represents a Rectangle(x, y, width, height). This class provides various methods
28 * for manipulating this Rectangle or creating new derived geometrical Objects.
29 */
30 public class Rectangle
31 : Cloneable, /+java.io.Serializable, +/Translatable
32 {
33 /** the X value */
34 public int x;
35 /** the Y value */
36 public int y;
37 /** the width*/
38 public int width;
39 /** the height */
40 public int height;
41
42 /**A singleton for use in short calculations. Use to avoid newing unnecessary objects.*/
43 public static const Rectangle SINGLETON;
44
45 static this(){
46 SINGLETON = new Rectangle();
47 }
48
49 static final long serialVersionUID = 1;
50
51 /**
52 * Constructs a Rectangle at the origin with zero width and height.
53 *
54 * @since 2.0
55 */
56 public this() { }
57
58 /**
59 * Constructs a Rectangle given a location and size.
60 *
61 * @param p the location
62 * @param size the size
63 * @since 2.0
64 */
65 public this(Point p, Dimension size) {
66 this(p.x, p.y, size.width, size.height);
67 }
68
69 /**
70 * Constructs a copy of the provided Rectangle.
71 *
72 * @param rect Rectangle supplying the initial values
73 * @since 2.0
74 */
75 public this(Rectangle rect) {
76 this(rect.x, rect.y, rect.width, rect.height);
77 }
78
79 /**
80 * Constructs a copy of the provided DWT {@link dwt.graphics.Rectangle}.
81 *
82 * @param rect The DWT Rectangle being copied
83 * @since 2.0
84 */
85 public this(dwt.graphics.Rectangle.Rectangle rect) {
86 this(rect.x, rect.y, rect.width, rect.height);
87 }
88
89 /**
90 * Constructs a Rectangle with the provided values.
91 *
92 * @param x X location
93 * @param y Y location
94 * @param width Width of the rectangle
95 * @param height Height of the rectangle
96 * @since 2.0
97 */
98 public this(int x, int y, int width, int height) {
99 this.x = x;
100 this.y = y;
101 this.width = width;
102 this.height = height;
103 }
104
105 /**
106 * Constructs the smallest Rectangle that contains the specified Points.
107 *
108 * @param p1 Upper left hand corner
109 * @param p2 Lower right hand corner
110 * @since 2.0
111 */
112 public this(Point p1, Point p2) {
113 this.x = Math.min(p1.x, p2.x);
114 this.y = Math.min(p1.y, p2.y);
115 this.width = Math.abs(p2.x - p1.x) + 1;
116 this.height = Math.abs(p2.y - p1.y) + 1;
117 }
118
119 /**
120 * Returns the y-coordinate of the bottom of this Rectangle.
121 *
122 * @return The Y coordinate of the bottom
123 * @since 2.0
124 */
125 public int bottom() {
126 return y + height;
127 }
128
129 /**
130 * Returns whether the given point is within the boundaries of this Rectangle.
131 * The boundaries are inclusive of the top and left edges, but exclusive of the
132 * bottom and right edges.
133 *
134 * @param pt Point being tested for containment
135 * @return true if the Point is within this Rectangle
136 * @since 2.0
137 */
138 public bool contains(Point pt) {
139 return contains(pt.x, pt.y);
140 }
141
142 /**
143 * Returns <code>true</code> if the given rectangle is contained within the
144 * boundaries of this Rectangle.
145 *
146 * @param rect the Rectangle to test
147 * @return true if the Rectangle is within this Rectangle
148 */
149 public bool contains(Rectangle rect) {
150 return x <= rect.x
151 && y <= rect.y
152 && right() >= rect.right()
153 && bottom() >= rect.bottom();
154 }
155
156 /**
157 * Returns whether the given coordinates are within the boundaries of this
158 * Rectangle. The boundaries are inclusive of the top and left edges, but
159 * exclusive of the bottom and right edges.
160 *
161 * @param x X value
162 * @param y Y value
163 * @return true if the coordinates are within this Rectangle
164 * @since 2.0
165 */
166 public bool contains(int x, int y) {
167 return y >= this.y
168 && y < this.y + this.height
169 && x >= this.x
170 && x < this.x + this.width;
171 }
172
173 /**
174 * Crops this rectangle by the amount specified in <code>insets</code>.
175 *
176 * @param insets Insets to be removed from the Rectangle
177 * @return <code>this</code> for convenience
178 * @since 2.0
179 */
180 public Rectangle crop(Insets insets) {
181 if (insets is null)
182 return this;
183 x += insets.left;
184 y += insets.top;
185 width -= (insets.getWidth());
186 height -= (insets.getHeight());
187 return this;
188 }
189
190 /**
191 * Returns whether the input object is equal to this Rectangle or not.
192 * Rectangles are equivalent if their x, y, height, and width values are the
193 * same.
194 *
195 * @param o Object being tested for equality
196 * @return Returns the result of the equality test
197 * @since 2.0
198 */
199 public override int opEquals(Object o) {
200 if (this is o) return true;
201 if (auto r = cast(Rectangle)o ) {
202 return (x is r.x)
203 && (y is r.y)
204 && (width is r.width)
205 && (height is r.height);
206 }
207 return false;
208 }
209
210 /**
211 * Expands the horizontal and vertical sides of this Rectangle with the values
212 * provided as input, and returns this for convenience. The location of its
213 * center is kept constant.
214 *
215 * @param h Horizontal increment
216 * @param v Vertical increment
217 * @return <code>this</code> for convenience
218 * @since 2.0
219 */
220 public Rectangle expand(int h, int v) {
221 return shrink(-h, -v);
222 }
223
224 /**
225 * Expands the horizontal and vertical sides of this Rectangle by the width and
226 * height of the given Insets, and returns this for convenience.
227 *
228 * @param insets contains the amounts to expand on each side
229 * @return <code>this</code> for convenience
230 * @since 2.0
231 */
232 public Rectangle expand(Insets insets) {
233 x -= insets.left;
234 y -= insets.top;
235 height += insets.getHeight();
236 width += insets.getWidth();
237 return this;
238 }
239
240 /**
241 * Returns a new Point representing the middle point of the bottom side of this
242 * Rectangle.
243 *
244 * @return Point at the bottom of the Rectangle
245 * @since 2.0
246 */
247 public Point getBottom() {
248 return new Point(x + width / 2, bottom());
249 }
250
251 /**
252 * Returns a new Point representing the bottom left point of this Rectangle.
253 *
254 * @return Point at the bottom left of the rectangle
255 * @since 2.0
256 */
257 public Point getBottomLeft() {
258 return new Point(x, y + height);
259 }
260
261 /**
262 * Returns a new Point representing the bottom right point of this Rectangle.
263 *
264 * @return Point at the bottom right of the rectangle
265 * @since 2.0
266 */
267 public Point getBottomRight() {
268 return new Point(x + width, y + height);
269 }
270
271 /**
272 * Returns a new point representing the center of this Rectangle.
273 *
274 * @return Point at the center of the rectangle
275 */
276 public Point getCenter() {
277 return new Point(x + width / 2, y + height / 2);
278 }
279
280 /**
281 * Returns a new Rectangle which has the exact same parameters as this
282 * Rectangle.
283 *
284 * @return Copy of this Rectangle
285 * @since 2.0
286 */
287 public Rectangle getCopy() {
288 // try {
289 // return cast(Rectangle)clone();
290 // } catch (CloneNotSupportedException exc) {
291 return new Rectangle(this);
292 // }
293 }
294
295 /**
296 * Returns a new Rectangle with the specified insets cropped.
297 *
298 * @param insets Insets being cropped from the Rectangle
299 * @return Cropped new Rectangle
300 */
301 public Rectangle getCropped(Insets insets) {
302 Rectangle r = new Rectangle(this);
303 r.crop(insets);
304 return r;
305 }
306
307 /**
308 * Returns a new incremented Rectangle, where the sides are expanded by the
309 * horizonatal and vertical values provided. The center of the Rectangle is
310 * maintained constant.
311 *
312 * @param h Horizontal increment
313 * @param v Vertical inrement
314 * @return A new expanded Rectangle
315 * @since 2.0
316 */
317 public Rectangle getExpanded(int h, int v) {
318 return (new Rectangle(this)).expand(h, v);
319 }
320
321 /**
322 * Creates and returns a new Rectangle with the bounds of <code>this</code>
323 * Rectangle, expanded by the given Insets.
324 *
325 * @param insets The insets used to expand this rectangle
326 * @return A new expanded Rectangle
327 * @since 2.0
328 */
329 public Rectangle getExpanded(Insets insets) {
330 return (new Rectangle(this)).expand(insets);
331 }
332
333
334 /**
335 * Returns a new Rectangle which has the intersection of this Rectangle and the
336 * rectangle provided as input. Returns an empty Rectangle if there is no
337 * interection.
338 *
339 * @param rect Rectangle provided to test for intersection
340 * @return A new Rectangle representing the intersection
341 * @since 2.0
342 */
343 public Rectangle getIntersection(Rectangle rect) {
344 int x1 = Math.max(x, rect.x);
345 int x2 = Math.min(x + width, rect.x + rect.width);
346 int y1 = Math.max(y, rect.y);
347 int y2 = Math.min(y + height, rect.y + rect.height);
348 if (((x2 - x1) < 0) || ((y2 - y1) < 0))
349 return new Rectangle(0, 0, 0, 0); // No intersection
350 else
351 return new Rectangle(x1, y1, x2 - x1, y2 - y1);
352 }
353
354 /**
355 * Returns a new Point representing the middle point of the left hand side of
356 * this Rectangle.
357 *
358 * @return Point at the left of the Rectangle
359 */
360 public Point getLeft() {
361 return new Point(x, y + height / 2);
362 }
363
364 /**
365 * Returns the upper left hand corner of the rectangle.
366 *
367 * @return Location of the rectangle
368 * @see #setLocation(Point)
369 */
370 public Point getLocation() {
371 return new Point(x, y);
372 }
373
374 /**
375 * <P>Returns an integer which represents the position of the given point with respect to
376 * this rectangle. Possible return values are bitwise ORs of the constants WEST, EAST,
377 * NORTH, and SOUTH as found in {@link dwtx.draw2d.PositionConstants}.
378 *
379 * <P>Returns PositionConstant.NONE if the given point is inside this Rectangle.
380 *
381 * @param pt The Point whose position has to be determined
382 * @return An <code>int</code> which is a PositionConstant
383 * @see dwtx.draw2d.PositionConstants
384 * @since 2.0
385 */
386 public int getPosition(Point pt) {
387 int result = PositionConstants.NONE;
388
389 if (contains(pt))
390 return result;
391
392 if (pt.x < x)
393 result = PositionConstants.WEST;
394 else if (pt.x >= (x + width))
395 result = PositionConstants.EAST;
396
397 if (pt.y < y)
398 result = result | PositionConstants.NORTH;
399 else if (pt.y >= (y + height))
400 result = result | PositionConstants.SOUTH;
401
402 return result;
403 }
404
405 /**
406 * Returns a new Rectangle which is equivalent to this Rectangle with its
407 * dimensions modified by the passed width <i>w</i> and height <i>h</i>.
408
409 * @param w Amount by which width is to be resized
410 * @param h Amount by which height is to be resized
411 * @return a new rectangle with its width and height modified
412 */
413 public Rectangle getResized(int w, int h) {
414 return (new Rectangle(this)).resize(w, h);
415 }
416
417 /**
418 * Returns a new Rectangle which is equivalent to this Rectangle with its
419 * dimensions modified by the passed Dimension <i>d</i>.
420 *
421 * @param d Dimensions by which the rectangle's size should be modified
422 * @return The new rectangle with the modified dimensions
423 * @since 2.0
424 */
425 public Rectangle getResized(Dimension d) {
426 return (new Rectangle(this)).resize(d);
427 }
428
429 /**
430 * Returns a new Point which represents the middle point of the right hand side
431 * of this Rectangle.
432 *
433 * @return Point at the right of the Rectangle
434 * @since 2.0
435 */
436 public Point getRight() {
437 return new Point(right(), y + height / 2);
438 }
439
440 /**
441 * Retuns the dimensions of this Rectangle.
442 *
443 * @return Size of this Rectangle as a Dimension
444 * @since 2.0
445 */
446 public Dimension getSize() {
447 return new Dimension(width, height);
448 }
449
450 /**
451 * Returns a new Point which represents the middle point of the top side of this
452 * Rectangle.
453 *
454 * @return Point at the top of the Rectangle
455 * @since 2.0
456 */
457 public Point getTop() {
458 return new Point(x + width / 2, y);
459 }
460
461 /**
462 * Returns a new Point which represents the top left hand corner of this
463 * Rectangle.
464 *
465 * @return Point at the top left of the rectangle
466 * @since 2.0
467 */
468 public Point getTopLeft() {
469 return new Point(x, y);
470 }
471
472 /**
473 * Returns a new Point which represents the top right hand corner of this
474 * Rectangle.
475 *
476 * @return Point at the top right of the rectangle
477 * @since 2.0
478 */
479 public Point getTopRight() {
480 return new Point(x + width, y);
481 }
482
483 /**
484 * Returns a new Rectangle which is shifted along each axis by the passed
485 * values.
486 *
487 * @param dx Displacement along X axis
488 * @param dy Displacement along Y axis
489 * @return The new translated rectangle
490 * @since 2.0
491 */
492 public Rectangle getTranslated(int dx, int dy) {
493 return (new Rectangle(this)).translate(dx, dy);
494 }
495
496 /**
497 * Returns a new Rectangle which is shifted by the position of the given Point.
498 *
499 * @param pt Point providing the amount of shift along each axis
500 * @return The new translated Rectangle
501 * @since 2.0
502 */
503 public Rectangle getTranslated(Point pt) {
504 return (new Rectangle(this)).translate(pt);
505 }
506
507 /**
508 * Returns a new rectangle whose width and height have been interchanged, as well
509 * as its x and y values. This can be useful in orientation changes.
510 *
511 * @return The transposed rectangle
512 * @since 2.0
513 */
514 public Rectangle getTransposed() {
515 Rectangle r = new Rectangle(this);
516 r.transpose();
517 return r;
518 }
519
520 /**
521 * Returns a new Rectangle which contains both this Rectangle and the Rectangle
522 * supplied as input.
523 *
524 * @param rect Rectangle for calculating union_
525 * @return A new unioned Rectangle
526 * @since 2.0
527 */
528 public Rectangle getUnion(Rectangle rect) {
529 if (rect is null || rect.isEmpty())
530 return new Rectangle(this);
531 Rectangle union_ = new Rectangle(
532 Math.min(x, rect.x),
533 Math.min(y, rect.y), 0, 0);
534 union_.width = Math.max(x + width, rect.x + rect.width) - union_.x;
535 union_.height = Math.max(y + height, rect.y + rect.height) - union_.y;
536 return union_;
537 }
538
539 /**
540 * @see java.lang.Object#toHash()
541 */
542 public override hash_t toHash() {
543 return (x + height + 1) * (y + width + 1) ^ x ^ y;
544 }
545
546 /**
547 * Sets the size of this Rectangle to the intersection region with the Rectangle
548 * supplied as input, and returns this for convenience. The location and
549 * dimensions are set to zero if there is no intersection with the input
550 * Rectangle.
551 *
552 * @param rect Rectangle for the calculating intersection.
553 * @return <code>this</code> for convenience
554 * @since 2.0
555 */
556 public Rectangle intersect(Rectangle rect) {
557 int x1 = Math.max(x, rect.x);
558 int x2 = Math.min(x + width, rect.x + rect.width);
559 int y1 = Math.max(y, rect.y);
560 int y2 = Math.min(y + height, rect.y + rect.height);
561 if (((x2 - x1) < 0) || ((y2 - y1) < 0))
562 x = y = width = height = 0; // No intersection
563 else {
564 x = x1;
565 y = y1;
566 width = x2 - x1;
567 height = y2 - y1;
568 }
569 return this;
570 }
571
572 /**
573 * Returns <code>true</code> if the input Rectangle intersects this Rectangle.
574 *
575 * @param rect Rectangle for the intersetion test
576 * @return <code>true</code> if the input Rectangle intersects this Rectangle
577 * @since 2.0
578 */
579 public bool intersects(Rectangle rect) {
580 return rect.x < x + width
581 && rect.y < y + height
582 && rect.x + rect.width > x
583 && rect.y + rect.height > y;
584 }
585
586 /**
587 * Returns <code>true</code> if this Rectangle's width or height is less than or
588 * equal to 0.
589 *
590 * @return <code>true</code> if this Rectangle is empty
591 * @since 2.0
592 */
593 public bool isEmpty() {
594 return width <= 0 || height <= 0;
595 }
596
597 /**
598 * @see Translatable#performScale(double)
599 */
600 public void performScale(double factor) {
601 scale(factor);
602 }
603
604 /**
605 * @see Translatable#performTranslate(int, int)
606 */
607 public void performTranslate(int dx, int dy) {
608 translate(dx, dy);
609 }
610
611 /**
612 * Resizes this Rectangle by the Dimension provided as input and returns this
613 * for convenience. This Rectange's width will become this.width + sizeDelta.width.
614 * Likewise for height.
615 *
616 * @param sizeDelta Resize data as a Dimension
617 * @return <code>this</code> for convenience
618 * @since 2.0
619 */
620 public Rectangle resize(Dimension sizeDelta) {
621 width += sizeDelta.width;
622 height += sizeDelta.height;
623 return this;
624 }
625
626 /**
627 * Resizes this Rectangle by the values supplied as input and returns this for
628 * convenience. This Rectangle's width will become this.width + dw. This
629 * Rectangle's height will become this.height + dh.
630 *
631 * @param dw Amount by which width is to be resized
632 * @param dh Amount by which height is to be resized
633 * @return <code>this</code> for convenience
634 * @since 2.0
635 */
636 public Rectangle resize(int dw, int dh) {
637 width += dw;
638 height += dh;
639 return this;
640 }
641
642 /**
643 * Returns the x-coordinate of the right side of this Rectangle.
644 *
645 * @return The X coordinate of the right side
646 * @since 2.0
647 */
648 public int right() {
649 return x + width;
650 }
651
652 /**
653 * Scales the location and size of this Rectangle by the given scale and returns
654 * this for convenience.
655 *
656 * @param scaleFactor The factor by which this rectangle will be scaled
657 * @return <code>this</code> for convenience
658 * @since 2.0
659 */
660 public final Rectangle scale(double scaleFactor) {
661 return scale(scaleFactor, scaleFactor);
662 }
663
664 /**
665 * Scales the location and size of this Rectangle by the given scales and returns
666 * this for convenience.
667 *
668 * @param scaleX the factor by which the X dimension has to be scaled
669 * @param scaleY the factor by which the Y dimension has to be scaled
670 * @return <code>this</code> for convenience
671 * @since 2.0
672 */
673 public Rectangle scale(double scaleX, double scaleY) {
674 int oldX = x;
675 int oldY = y;
676 x = cast(int)(Math.floor(x * scaleX));
677 y = cast(int)(Math.floor(y * scaleY));
678 width = cast(int)(Math.ceil((oldX + width) * scaleX)) - x;
679 height = cast(int)(Math.ceil((oldY + height) * scaleY)) - y;
680 return this;
681 }
682
683 /**
684 * Sets the parameters of this Rectangle from the Rectangle passed in and
685 * returns this for convenience.
686 *
687 * @return <code>this</code> for convenience
688 * @param rect Rectangle providing the bounding values
689 * @since 2.0
690 */
691 public Rectangle setBounds(Rectangle rect) {
692 x = rect.x;
693 y = rect.y;
694 width = rect.width;
695 height = rect.height;
696 return this;
697 }
698
699 /**
700 * Sets the location of this Rectangle to the point given as input and returns
701 * this for convenience.
702 *
703 * @return <code>this</code> for convenience
704 * @param p New position of this Rectangle
705 * @since 2.0
706 */
707 public Rectangle setLocation(Point p) {
708 x = p.x;
709 y = p.y;
710 return this;
711 }
712
713 /**
714 * Sets the location of this Rectangle to the coordinates given as input and
715 * returns this for convenience.
716 *
717 * @param x1 The new X coordinate
718 * @param y1 The new Y coordinate
719 * @return <code>this</code> for convenience
720 * @since 2.0
721 */
722 public Rectangle setLocation(int x1, int y1) {
723 x = x1;
724 y = y1;
725 return this;
726 }
727
728 /**
729 * Sets the width and height of this Rectangle to the width and height of the
730 * given Dimension and returns this for convenience.
731 *
732 * @param d The new Dimension
733 * @return <code>this</code> for convenience
734 * @since 2.0
735 */
736 public Rectangle setSize(Dimension d) {
737 width = d.width;
738 height = d.height;
739 return this;
740 }
741
742 /**
743 * Sets the width of this Rectangle to <i>w</i> and the height of this
744 * Rectangle to <i>h</i> and returns this for convenience.
745 *
746 * @return <code>this</code> for convenience
747 * @param w The new width
748 * @param h The new height
749 * @since 2.0
750 */
751 public Rectangle setSize(int w, int h) {
752 width = w;
753 height = h;
754 return this;
755 }
756
757 /**
758 * Shrinks the sides of this Rectangle by the horizontal and vertical values
759 * provided as input, and returns this Rectangle for convenience. The center of
760 * this Rectangle is kept constant.
761 *
762 * @param h Horizontal reduction amount
763 * @param v Vertical reduction amount
764 * @return <code>this</code> for convenience
765 * @since 2.0
766 */
767 public Rectangle shrink(int h, int v) {
768 x += h;
769 width -= (h + h);
770 y += v;
771 height -= (v + v);
772 return this;
773 }
774
775 /**
776 * Returns the description of this Rectangle.
777 *
778 * @return String containing the description
779 * @since 2.0
780 */
781 public override String toString() {
782 return Format("Rectangle({}, {}, {}, {})", x, y, width, height );
783 }
784
785 /**
786 * Returns <code>true</code> if the input Rectangle touches this Rectangle.
787 *
788 * @param rect Rectangle being checked for contact
789 * @return <code>true</code> if rect touches this Rectangle
790 * @since 2.0
791 */
792 public bool touches(Rectangle rect) {
793 return rect.x <= x + width
794 && rect.y <= y + height
795 && rect.x + rect.width >= x
796 && rect.y + rect.height >= y;
797 }
798
799 /**
800 * Moves this Rectangle horizontally by the x value of the given Point and
801 * vertically by the y value of the given Point, then returns this Rectangle for
802 * convenience.
803 *
804 * @param p Point which provides translation information
805 * @return <code>this</code> for convenience
806 */
807 public Rectangle translate(Point p) {
808 x += p.x;
809 y += p.y;
810 return this;
811 }
812
813 /**
814 * Moves this Rectangle horizontally by dx and vertically by dy, then returns
815 * this Rectangle for convenience.
816 *
817 * @param dx Shift along X axis
818 * @param dy Shift along Y axis
819 * @return <code>this</code> for convenience
820 * @since 2.0
821 */
822 public Rectangle translate(int dx, int dy) {
823 x += dx;
824 y += dy;
825 return this;
826 }
827
828 /**
829 * Switches the x and y values, as well as the width and height of this Rectangle.
830 * Useful for orientation changes.
831 *
832 * @return <code>this</code> for convenience
833 * @since 2.0
834 */
835 public Rectangle transpose() {
836 int temp = x;
837 x = y;
838 y = temp;
839 temp = width;
840 width = height;
841 height = temp;
842 return this;
843 }
844
845 /**
846 * Unions this Rectangle's width and height with the specified Dimension.
847 *
848 * @param d Dimension being unioned
849 * @return <code>this</code> for convenience
850 * @since 2.0
851 */
852 public Rectangle union_(Dimension d) {
853 width = Math.max(width, d.width);
854 height = Math.max(height, d.height);
855 return this;
856 }
857
858 /**
859 * Updates this Rectangle's bounds to the minimum size which can hold both this
860 * Rectangle and the coordinate (x,y).
861 *
862 * @return <code>this</code> for convenience
863 * @param x1 X coordinate
864 * @param y1 Y coordinate
865 * @since 2.0
866 */
867 public Rectangle union_(int x1, int y1) {
868 if (x1 < x) {
869 width += (x - x1);
870 x = x1;
871 } else {
872 int right = x + width;
873 if (x1 >= right) {
874 right = x1 + 1;
875 width = right - x;
876 }
877 }
878 if (y1 < y) {
879 height += (y - y1);
880 y = y1;
881 } else {
882 int bottom = y + height;
883 if (y1 >= bottom) {
884 bottom = y1 + 1;
885 height = bottom - y;
886 }
887 }
888 return this;
889 }
890
891 /**
892 * Updates this Rectangle's bounds to the minimum size which can hold both this
893 * Rectangle and the given Point.
894 *
895 * @param p Point to be unioned with this Rectangle
896 * @since 2.0
897 */
898 public void union_(Point p) {
899 union_(p.x, p.y);
900 }
901
902 /**
903 * Updates this Rectangle's dimensions to the minimum size which can hold both
904 * this Rectangle and the given Rectangle.
905 *
906 * @return <code>this</code> for convenience
907 * @param rect Rectangle to be unioned with this Rectangle
908 * @since 2.0
909 */
910 public Rectangle union_(Rectangle rect) {
911 if (rect is null)
912 return this;
913 return union_(rect.x, rect.y, rect.width, rect.height);
914 }
915
916 /**
917 * Updates this Rectangle's dimensions to the minimum size which can hold both
918 * this Rectangle and the rectangle (x, y, w, h).
919 *
920 * @param x X coordiante of desired union_.
921 * @param y Y coordiante of desired union_.
922 * @param w Width of desired union_.
923 * @param h Height of desired union_.
924 * @return <code>this</code> for convenience
925 * @since 2.0
926 */
927 public Rectangle union_(int x, int y, int w, int h) {
928 int right = Math.max(this.x + width, x + w);
929 int bottom = Math.max(this.y + height, y + h);
930 this.x = Math.min(this.x, x);
931 this.y = Math.min(this.y, y);
932 this.width = right - this.x;
933 this.height = bottom - this.y;
934 return this;
935 }
936
937 /**
938 * Returns <code>double</code> x coordinate
939 *
940 * @return <code>double</code> x coordinate
941 * @since 3.4
942 */
943 public double preciseX() {
944 return x;
945 }
946
947 /**
948 * Returns <code>double</code> y coordinate
949 *
950 * @return <code>double</code> y coordinate
951 * @since 3.4
952 */
953 public double preciseY() {
954 return y;
955 }
956
957 /**
958 * Returns <code>double</code> width
959 *
960 * @return <code>double</code> width
961 * @since 3.4
962 */
963 public double preciseWidth() {
964 return width;
965 }
966
967 /**
968 * Returns <code>double</code> height
969 *
970 * @return <code>double</code> height
971 * @since 3.4
972 */
973 public double preciseHeight() {
974 return height;
975 }
976
977 }