001    /* Rectangle2D.java -- generic rectangles in 2-D space
002       Copyright (C) 2000, 2001, 2002, 2004  Free Software Foundation
003    
004    This file is part of GNU Classpath.
005    
006    GNU Classpath is free software; you can redistribute it and/or modify
007    it under the terms of the GNU General Public License as published by
008    the Free Software Foundation; either version 2, or (at your option)
009    any later version.
010    
011    GNU Classpath is distributed in the hope that it will be useful, but
012    WITHOUT ANY WARRANTY; without even the implied warranty of
013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014    General Public License for more details.
015    
016    You should have received a copy of the GNU General Public License
017    along with GNU Classpath; see the file COPYING.  If not, write to the
018    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019    02110-1301 USA.
020    
021    Linking this library statically or dynamically with other modules is
022    making a combined work based on this library.  Thus, the terms and
023    conditions of the GNU General Public License cover the whole
024    combination.
025    
026    As a special exception, the copyright holders of this library give you
027    permission to link this library with independent modules to produce an
028    executable, regardless of the license terms of these independent
029    modules, and to copy and distribute the resulting executable under
030    terms of your choice, provided that you also meet, for each linked
031    independent module, the terms and conditions of the license of that
032    module.  An independent module is a module which is not derived from
033    or based on this library.  If you modify this library, you may extend
034    this exception to your version of the library, but you are not
035    obligated to do so.  If you do not wish to do so, delete this
036    exception statement from your version. */
037    
038    
039    package java.awt.geom;
040    
041    import java.util.NoSuchElementException;
042    
043    /**
044     * This class describes a rectangle by a point (x,y) and dimension (w x h).
045     * The actual storage is left up to subclasses.
046     *
047     * <p>It is valid for a rectangle to have negative width or height; but it
048     * is considered to have no area or internal points. Therefore, the behavior
049     * in methods like <code>contains</code> or <code>intersects</code> is
050     * undefined unless the rectangle has positive width and height.
051     *
052     * @author Tom Tromey (tromey@cygnus.com)
053     * @author Eric Blake (ebb9@email.byu.edu)
054     * @since 1.2
055     * @status updated to 1.4
056     */
057    public abstract class Rectangle2D extends RectangularShape
058    {
059      /**
060       * The point lies left of the rectangle (p.x &lt; r.x).
061       *
062       * @see #outcode(double, double)
063       */
064      public static final int OUT_LEFT = 1;
065    
066      /**
067       * The point lies above the rectangle (p.y &lt; r.y).
068       *
069       * @see #outcode(double, double)
070       */
071      public static final int OUT_TOP = 2;
072    
073      /**
074       * The point lies right of the rectangle (p.x &gt; r.maxX).
075       *
076       * @see #outcode(double, double)
077       */
078      public static final int OUT_RIGHT = 4;
079    
080      /**
081       * The point lies below of the rectangle (p.y &gt; r.maxY).
082       *
083       * @see #outcode(double, double)
084       */
085      public static final int OUT_BOTTOM = 8;
086    
087      /**
088       * Default constructor.
089       */
090      protected Rectangle2D()
091      {
092      }
093    
094      /**
095       * Set the bounding box of this rectangle.
096       *
097       * @param x the new X coordinate
098       * @param y the new Y coordinate
099       * @param w the new width
100       * @param h the new height
101       */
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       */
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       */
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       */
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       */
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       */
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       */
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       */
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       */
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       */
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       */
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       */
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       */
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       */
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       */
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 newx the X coordinate of the point to add to this rectangle
339       * @param newy the Y coordinate of the point to add to this rectangle
340       */
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       */
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, Rectangle2D, Rectangle2D)
372       */
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 at an optional transform to apply to the iterator
386       * @return a new iterator over the boundary
387       * @since 1.2
388       */
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 at an optional transform to apply to the iterator
494       * @param flatness the maximum distance for deviation from the real boundary
495       * @return a new iterator over the boundary
496       * @since 1.2
497       */
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 &gt;&gt; 32) ^ l);
512       * </pre>
513       *
514       * @return the hashcode
515       */
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       */
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         */
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         */
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         */
592        public double getX()
593        {
594          return x;
595        }
596    
597        /**
598         * Return the Y coordinate.
599         *
600         * @return the value of y
601         */
602        public double getY()
603        {
604          return y;
605        }
606    
607        /**
608         * Return the width.
609         *
610         * @return the value of width
611         */
612        public double getWidth()
613        {
614          return width;
615        }
616    
617        /**
618         * Return the height.
619         *
620         * @return the value of height
621         */
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         */
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         */
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         */
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         */
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         */
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         */
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         */
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         */
745        public String toString()
746        {
747          return getClass().getName() + "[x=" + x + ",y=" + y + ",w=" + width
748            + ",h=" + height + ']';
749        }
750      }
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         */
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         */
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         */
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         */
817        public double getX()
818        {
819          return x;
820        }
821    
822        /**
823         * Return the Y coordinate.
824         *
825         * @return the value of y
826         */
827        public double getY()
828        {
829          return y;
830        }
831    
832        /**
833         * Return the width.
834         *
835         * @return the value of width
836         */
837        public double getWidth()
838        {
839          return width;
840        }
841    
842        /**
843         * Return the height.
844         *
845         * @return the value of height
846         */
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         */
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         */
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         */
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         */
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         */
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         */
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         */
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         */
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         */
986        public String toString()
987        {
988          return getClass().getName() + "[x=" + x + ",y=" + y + ",w=" + width
989            + ",h=" + height + ']';
990        }
991      }
992    }