1 /* Rectangle2D.java -- generic rectangles in 2-D space
2    Copyright (C) 2000, 2001, 2002 Free Software Foundation
3 
4 This file is part of GNU Classpath.
5 
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10 
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA.
20 
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25 
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37 
38 
39 package java.awt.geom;
40 
41 import java.util.NoSuchElementException;
42 
43 /**
44  * This class describes a rectangle by a point (x,y) and dimension (w x h).
45  * The actual storage is left up to subclasses.
46  *
47  * <p>It is valid for a rectangle to have negative width or height; but it
48  * is considered to have no area or internal points. Therefore, the behavior
49  * in methods like <code>contains</code> or <code>intersects</code> is
50  * undefined unless the rectangle has positive width and height.
51  *
52  * @author Tom Tromey <tromey@cygnus.com>
53  * @author Eric Blake <ebb9@email.byu.edu>
54  * @since 1.2
55  * @status updated to 1.4
56  */
57 public abstract class Rectangle2D extends RectangularShape
58 {
59   /**
60    * The point lies left of the rectangle (p.x < r.x).
61    *
62    * @see #outcode()
63    */
64   public static final int OUT_LEFT = 1;
65 
66   /**
67    * The point lies above the rectangle (p.y < r.y).
68    *
69    * @see #outcode()
70    */
71   public static final int OUT_TOP = 2;
72 
73   /**
74    * The point lies right of the rectangle (p.x > r.maxX).
75    *
76    * @see #outcode()
77    */
78   public static final int OUT_RIGHT = 4;
79 
80   /**
81    * The point lies below of the rectangle (p.y > r.maxY).
82    *
83    * @see #outcode()
84    */
85   public static final int OUT_BOTTOM = 8;
86 
87   /**
88    * Default constructor.
89    */
Rectangle2D()90   protected Rectangle2D()
91   {
92   }
93 
94   /**
95    * Set the bounding box of this rectangle.
96    *
97    * @param x the new X coordinate
98    * @param y the new Y coordinate
99    * @param w the new width
100    * @param h the new height
101    */
setRect(double x, double y, double w, double h)102   public abstract void setRect(double x, double y, double w, double h);
103 
104   /**
105    * Set the bounding box of this rectangle from the given one.
106    *
107    * @param r rectangle to copy
108    * @throws NullPointerException if r is null
109    */
setRect(Rectangle2D r)110   public void setRect(Rectangle2D r)
111   {
112     setRect(r.getX(), r.getY(), r.getWidth(), r.getHeight());
113   }
114 
115   /**
116    * Tests if the specified line intersects the interior of this rectangle.
117    *
118    * @param x1 the first x coordinate of line segment
119    * @param y1 the first y coordinate of line segment
120    * @param x2 the second x coordinate of line segment
121    * @param y2 the second y coordinate of line segment
122    * @return true if the line intersects the rectangle
123    */
intersectsLine(double x1, double y1, double x2, double y2)124   public boolean intersectsLine(double x1, double y1, double x2, double y2)
125   {
126     double x = getX();
127     double y = getY();
128     double w = getWidth();
129     double h = getHeight();
130     if (w <= 0 || h <= 0)
131       return false;
132 
133     if (x1 >= x && x1 <= x + w && y1 >= y && y1 <= y + h)
134       return true;
135     if (x2 >= x && x2 <= x + w && y2 >= y && y2 <= y + h)
136       return true;
137 
138     double x3 = x + w;
139     double y3 = y + h;
140 
141     return (Line2D.linesIntersect(x1, y1, x2, y2, x, y, x, y3)
142             || Line2D.linesIntersect(x1, y1, x2, y2, x, y3, x3, y3)
143             || Line2D.linesIntersect(x1, y1, x2, y2, x3, y3, x3, y)
144             || Line2D.linesIntersect(x1, y1, x2, y2, x3, y, x, y));
145   }
146 
147   /**
148    * Tests if the specified line intersects the interior of this rectangle.
149    *
150    * @param l the line segment
151    * @return true if the line intersects the rectangle
152    * @throws NullPointerException if l is null
153    */
intersectsLine(Line2D l)154   public boolean intersectsLine(Line2D l)
155   {
156     return intersectsLine(l.getX1(), l.getY1(), l.getX2(), l.getY2());
157   }
158 
159   /**
160    * Determine where the point lies with respect to this rectangle. The
161    * result will be the binary OR of the appropriate bit masks.
162    *
163    * @param x the x coordinate to check
164    * @param y the y coordinate to check
165    * @return the binary OR of the result
166    * @see #OUT_LEFT
167    * @see #OUT_TOP
168    * @see #OUT_RIGHT
169    * @see #OUT_BOTTOM
170    */
outcode(double x, double y)171   public abstract int outcode(double x, double y);
172 
173   /**
174    * Determine where the point lies with respect to this rectangle. The
175    * result will be the binary OR of the appropriate bit masks.
176    *
177    * @param p the point to check
178    * @return the binary OR of the result
179    * @throws NullPointerException if p is null
180    * @see #OUT_LEFT
181    * @see #OUT_TOP
182    * @see #OUT_RIGHT
183    * @see #OUT_BOTTOM
184    */
outcode(Point2D p)185   public int outcode(Point2D p)
186   {
187     return outcode(p.getX(), p.getY());
188   }
189 
190   /**
191    * Set the bounding box of this rectangle.
192    *
193    * @param x the new X coordinate
194    * @param y the new Y coordinate
195    * @param w the new width
196    * @param h the new height
197    */
setFrame(double x, double y, double w, double h)198   public void setFrame(double x, double y, double w, double h)
199   {
200     setRect(x, y, w, h);
201   }
202 
203   /**
204    * Returns the bounds of this rectangle. A pretty useless method, as this
205    * is already a rectangle.
206    *
207    * @return a copy of this rectangle
208    */
getBounds2D()209   public Rectangle2D getBounds2D()
210   {
211     return (Rectangle2D) clone();
212   }
213 
214   /**
215    * Test if the given point is contained in the rectangle.
216    *
217    * @param x the x coordinate of the point
218    * @param y the y coordinate of the point
219    * @return true if (x,y) is in the rectangle
220    */
contains(double x, double y)221   public boolean contains(double x, double y)
222   {
223     double mx = getX();
224     double my = getY();
225     double w = getWidth();
226     double h = getHeight();
227     return w > 0 && h > 0 && x >= mx && x < mx + w && y >= my && y < my + h;
228   }
229 
230   /**
231    * Tests if the given rectangle intersects this one. In other words, test if
232    * the two rectangles share at least one internal point.
233    *
234    * @param x the x coordinate of the other rectangle
235    * @param y the y coordinate of the other rectangle
236    * @param w the width of the other rectangle
237    * @param h the height of the other rectangle
238    * @return true if the rectangles intersect
239    */
intersects(double x, double y, double w, double h)240   public boolean intersects(double x, double y, double w, double h)
241   {
242     double mx = getX();
243     double my = getY();
244     double mw = getWidth();
245     double mh = getHeight();
246     return w > 0 && h > 0 && mw > 0 && mh > 0
247       && x < mx + mw && x + w > mx && y < my + mh && y + h > my;
248   }
249 
250   /**
251    * Tests if this rectangle contains the given one. In other words, test if
252    * this rectangle contains all points in the given one.
253    *
254    * @param x the x coordinate of the other rectangle
255    * @param y the y coordinate of the other rectangle
256    * @param w the width of the other rectangle
257    * @param h the height of the other rectangle
258    * @return true if this rectangle contains the other
259    */
contains(double x, double y, double w, double h)260   public boolean contains(double x, double y, double w, double h)
261   {
262     double mx = getX();
263     double my = getY();
264     double mw = getWidth();
265     double mh = getHeight();
266     return w > 0 && h > 0 && mw > 0 && mh > 0
267       && x >= mx && x + w <= mx + mw && y >= my && y + h <= my + mh;
268   }
269 
270   /**
271    * Return a new rectangle which is the intersection of this and the given
272    * one. The result will be empty if there is no intersection.
273    *
274    * @param r the rectangle to be intersected
275    * @return the intersection
276    * @throws NullPointerException if r is null
277    */
createIntersection(Rectangle2D r)278   public abstract Rectangle2D createIntersection(Rectangle2D r);
279 
280   /**
281    * Intersects a pair of rectangles, and places the result in the
282    * destination; this can be used to avoid object creation. This method
283    * even works when the destination is also a source, although you stand
284    * to lose the original data.
285    *
286    * @param src1 the first source
287    * @param src2 the second source
288    * @param dest the destination for the intersection
289    * @throws NullPointerException if any rectangle is null
290    */
intersect(Rectangle2D src1, Rectangle2D src2, Rectangle2D dest)291   public static void intersect(Rectangle2D src1, Rectangle2D src2,
292                                Rectangle2D dest)
293   {
294     double x = Math.max(src1.getX(), src2.getX());
295     double y = Math.max(src1.getY(), src2.getY());
296     double maxx = Math.min(src1.getMaxX(), src2.getMaxX());
297     double maxy = Math.min(src1.getMaxY(), src2.getMaxY());
298     dest.setRect(x, y, maxx - x, maxy - y);
299   }
300 
301   /**
302    * Return a new rectangle which is the union of this and the given one.
303    *
304    * @param r the rectangle to be merged
305    * @return the union
306    * @throws NullPointerException if r is null
307    */
createUnion(Rectangle2D r)308   public abstract Rectangle2D createUnion(Rectangle2D r);
309 
310   /**
311    * Joins a pair of rectangles, and places the result in the destination;
312    * this can be used to avoid object creation. This method even works when
313    * the destination is also a source, although you stand to lose the
314    * original data.
315    *
316    * @param src1 the first source
317    * @param src2 the second source
318    * @param dest the destination for the union
319    * @throws NullPointerException if any rectangle is null
320    */
union(Rectangle2D src1, Rectangle2D src2, Rectangle2D dest)321   public static void union(Rectangle2D src1, Rectangle2D src2,
322                            Rectangle2D dest)
323   {
324     double x = Math.min(src1.getX(), src2.getX());
325     double y = Math.min(src1.getY(), src2.getY());
326     double maxx = Math.max(src1.getMaxX(), src2.getMaxX());
327     double maxy = Math.max(src1.getMaxY(), src2.getMaxY());
328     dest.setRect(x, y, maxx - x, maxy - y);
329   }
330 
331   /**
332    * Modifies this rectangle so that it represents the smallest rectangle
333    * that contains both the existing rectangle and the specified point.
334    * However, if the point falls on one of the two borders which are not
335    * inside the rectangle, a subsequent call to <code>contains</code> may
336    * return false.
337    *
338    * @param x the X coordinate of the point to add to this rectangle
339    * @param y the Y coordinate of the point to add to this rectangle
340    */
add(double newx, double newy)341   public void add(double newx, double newy)
342   {
343     double minx = Math.min(getX(), newx);
344     double maxx = Math.max(getMaxX(), newx);
345     double miny = Math.min(getY(), newy);
346     double maxy = Math.max(getMaxY(), newy);
347     setRect(minx, miny, maxx - minx, maxy - miny);
348   }
349 
350   /**
351    * Modifies this rectangle so that it represents the smallest rectangle
352    * that contains both the existing rectangle and the specified point.
353    * However, if the point falls on one of the two borders which are not
354    * inside the rectangle, a subsequent call to <code>contains</code> may
355    * return false.
356    *
357    * @param p the point to add to this rectangle
358    * @throws NullPointerException if p is null
359    */
add(Point2D p)360   public void add(Point2D p)
361   {
362     add(p.getX(), p.getY());
363   }
364 
365   /**
366    * Modifies this rectangle so that it represents the smallest rectangle
367    * that contains both the existing rectangle and the specified rectangle.
368    *
369    * @param r the rectangle to add to this rectangle
370    * @throws NullPointerException if r is null
371    * @see #union(Rectangle2D)
372    */
add(Rectangle2D r)373   public void add(Rectangle2D r)
374   {
375     union(this, r, this);
376   }
377 
378   /**
379    * Return an iterator along the shape boundary. If the optional transform
380    * is provided, the iterator is transformed accordingly. Each call returns
381    * a new object, independent from others in use. This iterator is thread
382    * safe; modifications to the rectangle do not affect the results of this
383    * path instance.
384    *
385    * @param transform an optional transform to apply to the iterator
386    * @return a new iterator over the boundary
387    * @since 1.2
388    */
getPathIterator(final AffineTransform at)389   public PathIterator getPathIterator(final AffineTransform at)
390   {
391     final double minx = getX();
392     final double miny = getY();
393     final double maxx = minx + getWidth();
394     final double maxy = miny + getHeight();
395     return new PathIterator()
396     {
397       /** Current coordinate. */
398       private int current = (maxx <= minx && maxy <= miny) ? 6 : 0;
399 
400       public int getWindingRule()
401       {
402         // A test program showed that Sun J2SE 1.3.1 and 1.4.1_01
403         // return WIND_NON_ZERO paths.  While this does not really
404         // make any difference for rectangles (because they are not
405         // self-intersecting), it seems appropriate to behave
406         // identically.
407 
408         return WIND_NON_ZERO;
409       }
410 
411       public boolean isDone()
412       {
413         return current > 5;
414       }
415 
416       public void next()
417       {
418         current++;
419       }
420 
421       public int currentSegment(float[] coords)
422       {
423         switch (current)
424           {
425           case 1:
426             coords[0] = (float) maxx;
427             coords[1] = (float) miny;
428             break;
429           case 2:
430             coords[0] = (float) maxx;
431             coords[1] = (float) maxy;
432             break;
433           case 3:
434             coords[0] = (float) minx;
435             coords[1] = (float) maxy;
436             break;
437           case 0:
438           case 4:
439             coords[0] = (float) minx;
440             coords[1] = (float) miny;
441             break;
442           case 5:
443             return SEG_CLOSE;
444           default:
445             throw new NoSuchElementException("rect iterator out of bounds");
446           }
447         if (at != null)
448           at.transform(coords, 0, coords, 0, 1);
449         return current == 0 ? SEG_MOVETO : SEG_LINETO;
450       }
451 
452       public int currentSegment(double[] coords)
453       {
454         switch (current)
455           {
456           case 1:
457             coords[0] = maxx;
458             coords[1] = miny;
459             break;
460           case 2:
461             coords[0] = maxx;
462             coords[1] = maxy;
463             break;
464           case 3:
465             coords[0] = minx;
466             coords[1] = maxy;
467             break;
468           case 0:
469           case 4:
470             coords[0] = minx;
471             coords[1] = miny;
472             break;
473           case 5:
474             return SEG_CLOSE;
475           default:
476             throw new NoSuchElementException("rect iterator out of bounds");
477           }
478         if (at != null)
479           at.transform(coords, 0, coords, 0, 1);
480         return current == 0 ? SEG_MOVETO : SEG_LINETO;
481       }
482     };
483   }
484 
485   /**
486    * Return an iterator along the shape boundary. If the optional transform
487    * is provided, the iterator is transformed accordingly. Each call returns
488    * a new object, independent from others in use. This iterator is thread
489    * safe; modifications to the rectangle do not affect the results of this
490    * path instance. As the rectangle is already flat, the flatness parameter
491    * is ignored.
492    *
493    * @param transform an optional transform to apply to the iterator
494    * @param double the maximum distance for deviation from the real boundary
495    * @return a new iterator over the boundary
496    * @since 1.2
497    */
getPathIterator(AffineTransform at, double flatness)498   public PathIterator getPathIterator(AffineTransform at, double flatness)
499   {
500     return getPathIterator(at);
501   }
502 
503   /**
504    * Return the hashcode for this rectangle. The formula is not documented, but
505    * appears to be the same as:
506    * <pre>
507    * long l = Double.doubleToLongBits(getX())
508    *   + 37 * Double.doubleToLongBits(getY())
509    *   + 43 * Double.doubleToLongBits(getWidth())
510    *   + 47 * Double.doubleToLongBits(getHeight());
511    * return (int) ((l >> 32) ^ l);
512    * </pre>
513    *
514    * @return the hashcode
515    */
hashCode()516   public int hashCode()
517   {
518     // Talk about a fun time reverse engineering this one!
519     long l = java.lang.Double.doubleToLongBits(getX())
520       + 37 * java.lang.Double.doubleToLongBits(getY())
521       + 43 * java.lang.Double.doubleToLongBits(getWidth())
522       + 47 * java.lang.Double.doubleToLongBits(getHeight());
523     return (int) ((l >> 32) ^ l);
524   }
525 
526   /**
527    * Tests this rectangle for equality against the specified object.  This
528    * will be true if an only if the specified object is an instance of
529    * Rectangle2D with the same coordinates and dimensions.
530    *
531    * @param obj the object to test against for equality
532    * @return true if the specified object is equal to this one
533    */
equals(Object obj)534   public boolean equals(Object obj)
535   {
536     if (! (obj instanceof Rectangle2D))
537       return false;
538     Rectangle2D r = (Rectangle2D) obj;
539     return r.getX() == getX() && r.getY() == getY()
540       && r.getWidth() == getWidth() && r.getHeight() == getHeight();
541   }
542 
543   /**
544    * This class defines a rectangle in <code>double</code> precision.
545    *
546    * @author Eric Blake <ebb9@email.byu.edu>
547    * @since 1.2
548    * @status updated to 1.4
549    */
550   public static class Double extends Rectangle2D
551   {
552     /** The x coordinate of the lower left corner. */
553     public double x;
554 
555     /** The y coordinate of the lower left corner. */
556     public double y;
557 
558     /** The width of the rectangle. */
559     public double width;
560 
561     /** The height of the rectangle. */
562     public double height;
563 
564     /**
565      * Create a rectangle at (0,0) with width 0 and height 0.
566      */
Double()567     public Double()
568     {
569     }
570 
571     /**
572      * Create a rectangle with the given values.
573      *
574      * @param x the x coordinate
575      * @param y the y coordinate
576      * @param w the width
577      * @param h the height
578      */
Double(double x, double y, double w, double h)579     public Double(double x, double y, double w, double h)
580     {
581       this.x = x;
582       this.y = y;
583       width = w;
584       height = h;
585     }
586 
587     /**
588      * Return the X coordinate.
589      *
590      * @return the value of x
591      */
getX()592     public double getX()
593     {
594       return x;
595     }
596 
597     /**
598      * Return the Y coordinate.
599      *
600      * @return the value of y
601      */
getY()602     public double getY()
603     {
604       return y;
605     }
606 
607     /**
608      * Return the width.
609      *
610      * @return the value of width
611      */
getWidth()612     public double getWidth()
613     {
614       return width;
615     }
616 
617     /**
618      * Return the height.
619      *
620      * @return the value of height
621      */
getHeight()622     public double getHeight()
623     {
624       return height;
625     }
626 
627     /**
628      * Test if the rectangle is empty.
629      *
630      * @return true if width or height is not positive
631      */
isEmpty()632     public boolean isEmpty()
633     {
634       return width <= 0 || height <= 0;
635     }
636 
637     /**
638      * Set the contents of this rectangle to those specified.
639      *
640      * @param x the x coordinate
641      * @param y the y coordinate
642      * @param w the width
643      * @param h the height
644      */
setRect(double x, double y, double w, double h)645     public void setRect(double x, double y, double w, double h)
646     {
647       this.x = x;
648       this.y = y;
649       width = w;
650       height = h;
651     }
652 
653     /**
654      * Set the contents of this rectangle to those specified.
655      *
656      * @param r the rectangle to copy
657      * @throws NullPointerException if r is null
658      */
setRect(Rectangle2D r)659     public void setRect(Rectangle2D r)
660     {
661       x = r.getX();
662       y = r.getY();
663       width = r.getWidth();
664       height = r.getHeight();
665     }
666 
667     /**
668      * Determine where the point lies with respect to this rectangle. The
669      * result will be the binary OR of the appropriate bit masks.
670      *
671      * @param x the x coordinate to check
672      * @param y the y coordinate to check
673      * @return the binary OR of the result
674      * @see #OUT_LEFT
675      * @see #OUT_TOP
676      * @see #OUT_RIGHT
677      * @see #OUT_BOTTOM
678      * @since 1.2
679      */
outcode(double x, double y)680     public int outcode(double x, double y)
681     {
682       int result = 0;
683       if (width <= 0)
684         result |= OUT_LEFT | OUT_RIGHT;
685       else if (x < this.x)
686         result |= OUT_LEFT;
687       else if (x > this.x + width)
688         result |= OUT_RIGHT;
689       if (height <= 0)
690         result |= OUT_BOTTOM | OUT_TOP;
691       else if (y < this.y) // Remember that +y heads top-to-bottom.
692         result |= OUT_TOP;
693       else if (y > this.y + height)
694         result |= OUT_BOTTOM;
695       return result;
696     }
697 
698     /**
699      * Returns the bounds of this rectangle. A pretty useless method, as this
700      * is already a rectangle.
701      *
702      * @return a copy of this rectangle
703      */
getBounds2D()704     public Rectangle2D getBounds2D()
705     {
706       return new Double(x, y, width, height);
707     }
708 
709     /**
710      * Return a new rectangle which is the intersection of this and the given
711      * one. The result will be empty if there is no intersection.
712      *
713      * @param r the rectangle to be intersected
714      * @return the intersection
715      * @throws NullPointerException if r is null
716      */
createIntersection(Rectangle2D r)717     public Rectangle2D createIntersection(Rectangle2D r)
718     {
719       Double res = new Double();
720       intersect(this, r, res);
721       return res;
722     }
723 
724     /**
725      * Return a new rectangle which is the union of this and the given one.
726      *
727      * @param r the rectangle to be merged
728      * @return the union
729      * @throws NullPointerException if r is null
730      */
createUnion(Rectangle2D r)731     public Rectangle2D createUnion(Rectangle2D r)
732     {
733       Double res = new Double();
734       union(this, r, res);
735       return res;
736     }
737 
738     /**
739      * Returns a string representation of this rectangle. This is in the form
740      * <code>getClass().getName() + "[x=" + x + ",y=" + y + ",w=" + width
741      * + ",h=" + height + ']'</code>.
742      *
743      * @return a string representation of this rectangle
744      */
toString()745     public String toString()
746     {
747       return getClass().getName() + "[x=" + x + ",y=" + y + ",w=" + width
748         + ",h=" + height + ']';
749     }
750   } // class Double
751 
752   /**
753    * This class defines a rectangle in <code>float</code> precision.
754    *
755    * @author Eric Blake <ebb9@email.byu.edu>
756    * @since 1.2
757    * @status updated to 1.4
758    */
759   public static class Float extends Rectangle2D
760   {
761     /** The x coordinate of the lower left corner. */
762     public float x;
763 
764     /** The y coordinate of the lower left corner. */
765     public float y;
766 
767     /** The width of the rectangle. */
768     public float width;
769 
770     /** The height of the rectangle. */
771     public float height;
772 
773     /**
774      * Create a rectangle at (0,0) with width 0 and height 0.
775      */
Float()776     public Float()
777     {
778     }
779 
780     /**
781      * Create a rectangle with the given values.
782      *
783      * @param x the x coordinate
784      * @param y the y coordinate
785      * @param w the width
786      * @param h the height
787      */
Float(float x, float y, float w, float h)788     public Float(float x, float y, float w, float h)
789     {
790       this.x = x;
791       this.y = y;
792       width = w;
793       height = h;
794     }
795 
796     /**
797      * Create a rectangle with the given values.
798      *
799      * @param x the x coordinate
800      * @param y the y coordinate
801      * @param w the width
802      * @param h the height
803      */
Float(double x, double y, double w, double h)804     Float(double x, double y, double w, double h)
805     {
806       this.x = (float) x;
807       this.y = (float) y;
808       width = (float) w;
809       height = (float) h;
810     }
811 
812     /**
813      * Return the X coordinate.
814      *
815      * @return the value of x
816      */
getX()817     public double getX()
818     {
819       return x;
820     }
821 
822     /**
823      * Return the Y coordinate.
824      *
825      * @return the value of y
826      */
getY()827     public double getY()
828     {
829       return y;
830     }
831 
832     /**
833      * Return the width.
834      *
835      * @return the value of width
836      */
getWidth()837     public double getWidth()
838     {
839       return width;
840     }
841 
842     /**
843      * Return the height.
844      *
845      * @return the value of height
846      */
getHeight()847     public double getHeight()
848     {
849       return height;
850     }
851 
852     /**
853      * Test if the rectangle is empty.
854      *
855      * @return true if width or height is not positive
856      */
isEmpty()857     public boolean isEmpty()
858     {
859       return width <= 0 || height <= 0;
860     }
861 
862     /**
863      * Set the contents of this rectangle to those specified.
864      *
865      * @param x the x coordinate
866      * @param y the y coordinate
867      * @param w the width
868      * @param h the height
869      */
setRect(float x, float y, float w, float h)870     public void setRect(float x, float y, float w, float h)
871     {
872       this.x = x;
873       this.y = y;
874       width = w;
875       height = h;
876     }
877 
878     /**
879      * Set the contents of this rectangle to those specified.
880      *
881      * @param x the x coordinate
882      * @param y the y coordinate
883      * @param w the width
884      * @param h the height
885      */
setRect(double x, double y, double w, double h)886     public void setRect(double x, double y, double w, double h)
887     {
888       this.x = (float) x;
889       this.y = (float) y;
890       width = (float) w;
891       height = (float) h;
892     }
893 
894     /**
895      * Set the contents of this rectangle to those specified.
896      *
897      * @param r the rectangle to copy
898      * @throws NullPointerException if r is null
899      */
setRect(Rectangle2D r)900     public void setRect(Rectangle2D r)
901     {
902       x = (float) r.getX();
903       y = (float) r.getY();
904       width = (float) r.getWidth();
905       height = (float) r.getHeight();
906     }
907 
908     /**
909      * Determine where the point lies with respect to this rectangle. The
910      * result will be the binary OR of the appropriate bit masks.
911      *
912      * @param x the x coordinate to check
913      * @param y the y coordinate to check
914      * @return the binary OR of the result
915      * @see #OUT_LEFT
916      * @see #OUT_TOP
917      * @see #OUT_RIGHT
918      * @see #OUT_BOTTOM
919      * @since 1.2
920      */
outcode(double x, double y)921     public int outcode(double x, double y)
922     {
923       int result = 0;
924       if (width <= 0)
925         result |= OUT_LEFT | OUT_RIGHT;
926       else if (x < this.x)
927         result |= OUT_LEFT;
928       else if (x > this.x + width)
929         result |= OUT_RIGHT;
930       if (height <= 0)
931         result |= OUT_BOTTOM | OUT_TOP;
932       else if (y < this.y) // Remember that +y heads top-to-bottom.
933         result |= OUT_TOP;
934       else if (y > this.y + height)
935         result |= OUT_BOTTOM;
936       return result;
937     }
938 
939     /**
940      * Returns the bounds of this rectangle. A pretty useless method, as this
941      * is already a rectangle.
942      *
943      * @return a copy of this rectangle
944      */
getBounds2D()945     public Rectangle2D getBounds2D()
946     {
947       return new Float(x, y, width, height);
948     }
949 
950     /**
951      * Return a new rectangle which is the intersection of this and the given
952      * one. The result will be empty if there is no intersection.
953      *
954      * @param r the rectangle to be intersected
955      * @return the intersection
956      * @throws NullPointerException if r is null
957      */
createIntersection(Rectangle2D r)958     public Rectangle2D createIntersection(Rectangle2D r)
959     {
960       Float res = new Float();
961       intersect(this, r, res);
962       return res;
963     }
964 
965     /**
966      * Return a new rectangle which is the union of this and the given one.
967      *
968      * @param r the rectangle to be merged
969      * @return the union
970      * @throws NullPointerException if r is null
971      */
createUnion(Rectangle2D r)972     public Rectangle2D createUnion(Rectangle2D r)
973     {
974       Float res = new Float();
975       union(this, r, res);
976       return res;
977     }
978 
979     /**
980      * Returns a string representation of this rectangle. This is in the form
981      * <code>getClass().getName() + "[x=" + x + ",y=" + y + ",w=" + width
982      * + ",h=" + height + ']'</code>.
983      *
984      * @return a string representation of this rectangle
985      */
toString()986     public String toString()
987     {
988       return getClass().getName() + "[x=" + x + ",y=" + y + ",w=" + width
989         + ",h=" + height + ']';
990     }
991   } // class Float
992 } // class Rectangle2D
993