/[classpath]/classpath/java/awt/geom/RectangularShape.java
ViewVC logotype

Diff of /classpath/java/awt/geom/RectangularShape.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.2 by mark, Tue Jan 22 22:26:59 2002 UTC revision 1.3 by ericb, Thu Mar 21 07:58:00 2002 UTC
# Line 1  Line 1 
1  /* Copyright (C) 2000, 2002  Free Software Foundation  /* RectangularShape.java -- a rectangular frame for several generic shapes
2       Copyright (C) 2000, 2002 Free Software Foundation
3    
4  This file is part of GNU Classpath.  This file is part of GNU Classpath.
5    
# Line 34  this exception to your version of the li Line 35  this exception to your version of the li
35  obligated to do so.  If you do not wish to do so, delete this  obligated to do so.  If you do not wish to do so, delete this
36  exception statement from your version. */  exception statement from your version. */
37    
38    
39  package java.awt.geom;  package java.awt.geom;
40  import java.awt.*;  
41  import java.awt.geom.Rectangle2D;  import java.awt.Rectangle;
42    import java.awt.Shape;
43    
44  /**  /**
45     * This class provides a generic framework, and several helper methods, for
46     * subclasses which represent geometric objects inside a rectangular frame.
47     * This does not specify any geometry except for the bounding box.
48     *
49   * @author Tom Tromey <tromey@cygnus.com>   * @author Tom Tromey <tromey@cygnus.com>
50   * @date April 16, 2000   * @author Eric Blake <ebb9@email.byu.edu>
51     * @since 1.2
52     * @see Arc2D
53     * @see Ellipse2D
54     * @see Rectangle2D
55     * @see RoundRectangle2D
56     * @status updated to 1.4
57   */   */
   
58  public abstract class RectangularShape implements Shape, Cloneable  public abstract class RectangularShape implements Shape, Cloneable
59  {  {
60    protected RectangularShape ()    /**
61    {     * Default constructor.
62    }     */
63      protected RectangularShape()
64    public abstract double getX ();    {
65    public abstract double getY ();    }
66    public abstract double getWidth ();  
67    public abstract double getHeight ();    /**
68       * Get the x coordinate of the upper-left corner of the framing rectangle.
69    public double getMinX ()     *
70    {         * @return the x coordinate
71      return Math.min (getX (), getX () + getWidth ());     */
72    }    public abstract double getX();
73    
74    public double getMinY ()    /**
75    {     * Get the y coordinate of the upper-left corner of the framing rectangle.
76      return Math.min (getY (), getY () + getHeight ());     *
77    }     * @return the y coordinate
78       */
79    public double getMaxX ()    public abstract double getY();
80    {      
81      return Math.max (getX (), getX () + getWidth ());    /**
82    }     * Get the width of the framing rectangle.
83       *
84    public double getMaxY ()     * @return the width
85    {     */
86      return Math.max (getY (), getY () + getHeight ());    public abstract double getWidth();
87    }  
88      /**
89    public double getCenterX ()     * Get the height of the framing rectangle.
90    {     *
91      return getX () + getWidth () / 2;     * @return the height
92    }     */
93      public abstract double getHeight();
94    public double getCenterY ()  
95    {    /**
96      return getY () + getHeight () / 2;     * Get the minimum x coordinate in the frame. This is misnamed, or else
97    }     * Sun has a bug, because the implementation returns getX() even when
98       * getWidth() is negative.
99    public Rectangle2D getFrame ()     *
100    {     * @return the minimum x coordinate
101      return new Rectangle2D.Double (getX (), getY (),     */
102                                     getWidth (), getHeight ());    public double getMinX()
103    }    {
104        return getX();
105    public abstract boolean isEmpty ();    }
106    public abstract void setFrame (double x, double y, double w, double h);  
107      /**
108    public void setFrame (Point2D loc, Dimension2D size)     * Get the minimum y coordinate in the frame. This is misnamed, or else
109    {     * Sun has a bug, because the implementation returns getY() even when
110      setFrame (loc.getX (), loc.getY (), size.getWidth (), size.getHeight ());     * getHeight() is negative.
111    }     *
112       * @return the minimum y coordinate
113    public void setFrame (Rectangle2D r)     */
114    {    public double getMinY()
115      setFrame (r.getX (), r.getY (), r.getWidth (), r.getHeight ());    {
116    }      return getY();
117      }
118    public void setFrameFromDiagonal (double x1, double y1,  
119                                      double x2, double y2)    /**
120       * Get the maximum x coordinate in the frame. This is misnamed, or else
121       * Sun has a bug, because the implementation returns getX()+getWidth() even
122       * when getWidth() is negative.
123       *
124       * @return the maximum x coordinate
125       */
126      public double getMaxX()
127      {
128        return getX() + getWidth();
129      }
130    
131      /**
132       * Get the maximum y coordinate in the frame. This is misnamed, or else
133       * Sun has a bug, because the implementation returns getY()+getHeight() even
134       * when getHeight() is negative.
135       *
136       * @return the maximum y coordinate
137       */
138      public double getMaxY()
139      {
140        return getY() + getHeight();
141      }
142    
143      /**
144       * Return the x coordinate of the center point of the framing rectangle.
145       *
146       * @return the central x coordinate
147       */
148      public double getCenterX()
149      {
150        return getX() + getWidth() / 2;
151      }
152    
153      /**
154       * Return the y coordinate of the center point of the framing rectangle.
155       *
156       * @return the central y coordinate
157       */
158      public double getCenterY()
159      {
160        return getY() + getHeight() / 2;
161      }
162    
163      /**
164       * Return the frame around this object. Note that this may be a looser
165       * bounding box than getBounds2D.
166       *
167       * @return the frame, in double precision
168       * @see #setFrame(double, double, double, double)
169       */
170      public Rectangle2D getFrame()
171      {
172        return new Rectangle2D.Double(getX(), getY(), getWidth(), getHeight());
173      }
174    
175      /**
176       * Test if the shape is empty, meaning that no points are inside it.
177       *
178       * @return true if the shape is empty
179       */
180      public abstract boolean isEmpty();
181    
182      /**
183       * Set the framing rectangle of this shape to the given coordinate and size.
184       *
185       * @param x the new x coordinate
186       * @param y the new y coordinate
187       * @param w the new width
188       * @param h the new height
189       * @see #getFrame()
190       */
191      public abstract void setFrame(double x, double y, double w, double h);
192    
193      /**
194       * Set the framing rectangle of this shape to the given coordinate and size.
195       *
196       * @param p the new point
197       * @param d the new dimension
198       * @throws NullPointerException if p or d is null
199       * @see #getFrame()
200       */
201      public void setFrame(Point2D p, Dimension2D d)
202      {
203        setFrame(p.getX(), p.getY(), d.getWidth(), d.getHeight());
204      }
205    
206      /**
207       * Set the framing rectangle of this shape to the given rectangle.
208       *
209       * @param r the new framing rectangle
210       * @throws NullPointerException if r is null
211       * @see #getFrame()
212       */
213      public void setFrame(Rectangle2D r)
214      {
215        setFrame(r.getX(), r.getY(), r.getWidth(), r.getHeight());
216      }
217    
218      /**
219       * Set the framing rectangle of this shape using two points on a diagonal.
220       * The area will be positive.
221       *
222       * @param x1 the first x coordinate
223       * @param y1 the first y coordinate
224       * @param x2 the second x coordinate
225       * @param y2 the second y coordinate
226       */
227      public void setFrameFromDiagonal(double x1, double y1, double x2, double y2)
228    {    {
229      if (x1 > x2)      if (x1 > x2)
230        {        {
# Line 118  public abstract class RectangularShape i Line 238  public abstract class RectangularShape i
238          y2 = y1;          y2 = y1;
239          y1 = t;          y1 = t;
240        }        }
241      setFrame (x1, y1, x2 - x1, y2 - y1);      setFrame(x1, y1, x2 - x1, y2 - y1);
   }  
   
   public void setFrameFromDiagonal (Point2D p1, Point2D p2)  
   {  
     setFrameFromDiagonal (p1.getX (), p1.getY (),  
                           p2.getX (), p2.getY ());  
   }  
   
   public void setFrameFromCenter (double centerX, double centerY,  
                                   double cornerX, double cornerY)  
   {  
     double halfw = Math.abs (cornerX - centerX);  
     double halfh = Math.abs (cornerY - centerY);  
     setFrame (centerX - halfw, centerY - halfh,  
               2 * halfw, 2 * halfh);  
   }  
   
   public void setFrameFromCenter (Point2D center, Point2D corner)  
   {  
     setFrameFromCenter (center.getX (), center.getY (),  
                         corner.getX (), corner.getY ());  
   }  
   
   public boolean contains (Point2D p)  
   {  
     double x = p.getX ();  
     double y = p.getY ();  
     double rx = getX ();  
     double ry = getY ();  
     double w = getWidth ();  
     double h = getHeight ();  
     return x >= rx && x < rx + w && y >= ry && y < ry + h;  
   }  
   
   public boolean intersects (Rectangle2D r)  
   {  
     double x = getX ();  
     double w = getWidth ();  
     double mx = r.getX ();  
     double mw = r.getWidth ();  
     if (x < mx || x >= mx + mw || x + w < mx || x + w >= mx + mw)  
       return false;  
     double y = getY ();  
     double h = getHeight ();  
     double my = r.getY ();  
     double mh = r.getHeight ();  
     return y >= my && y < my + mh && y + h >= my && y + h < my + mh;  
242    }    }
243    
244    private boolean containsPoint (double x, double y)    /**
245    {     * Set the framing rectangle of this shape using two points on a diagonal.
246      double mx = getX ();     * The area will be positive.
247      double mw = getWidth ();     *
248      if (x < mx || x >= mx + mw)     * @param p1 the first point
249        return false;     * @param p2 the second point
250      double my = getY ();     * @throws NullPointerException if either point is null
251      double mh = getHeight ();     */
252      return y >= my && y < my + mh;    public void setFrameFromDiagonal(Point2D p1, Point2D p2)
253    }    {
254        setFrameFromDiagonal(p1.getX(), p1.getY(), p2.getX(), p2.getY());
255    public boolean contains (Rectangle2D r)    }
256    {  
257      return (containsPoint (r.getMinX (), r.getMinY ())    /**
258              && containsPoint (r.getMaxX (), r.getMaxY ()));     * Set the framing rectangle of this shape using the center of the frame,
259    }     * and one of the four corners. The area will be positive.
260       *
261    public Rectangle getBounds ()     * @param centerX the x coordinate at the center
262    {     * @param centerY the y coordinate at the center
263      return new Rectangle ((int) getX (), (int) getY (),     * @param cornerX the x coordinate at a corner
264                            (int) getWidth (), (int) getHeight ());     * @param cornerY the y coordinate at a corner
265    }     */
266      public void setFrameFromCenter(double centerX, double centerY,
267    public PathIterator getPathIterator (AffineTransform at, double flatness)                                   double cornerX, double cornerY)
268    {    {
269      return at.new Iterator (new Iterator ());      double halfw = Math.abs(cornerX - centerX);
270    }      double halfh = Math.abs(cornerY - centerY);
271        setFrame(centerX - halfw, centerY - halfh, halfw + halfw, halfh + halfh);
272    public Object clone ()    }
273    
274      /**
275       * Set the framing rectangle of this shape using the center of the frame,
276       * and one of the four corners. The area will be positive.
277       *
278       * @param center the center point
279       * @param corner a corner point
280       * @throws NullPointerException if either point is null
281       */
282      public void setFrameFromCenter(Point2D center, Point2D corner)
283      {
284        setFrameFromCenter(center.getX(), center.getY(),
285                           corner.getX(), corner.getY());
286      }
287    
288      /**
289       * Tests if a point is inside the boundary of the shape.
290       *
291       * @param p the point to test
292       * @return true if the point is inside the shape
293       * @throws NullPointerException if p is null
294       * @see #contains(double, double)
295       */
296      public boolean contains(Point2D p)
297      {
298        return contains(p.getX(), p.getY());
299      }
300    
301      /**
302       * Tests if a rectangle and this shape share common internal points.
303       *
304       * @param r the rectangle to test
305       * @return true if the rectangle intersects this shpae
306       * @throws NullPointerException if r is null
307       * @see #intersects(double, double, double, double)
308       */
309      public boolean intersects(Rectangle2D r)
310      {
311        return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
312      }
313    
314      /**
315       * Tests if the shape completely contains the given rectangle.
316       *
317       * @param r the rectangle to test
318       * @return true if r is contained in this shape
319       * @throws NullPointerException if r is null
320       * @see #contains(double, double, double, double)
321       */
322      public boolean contains(Rectangle2D r)
323      {
324        return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
325      }
326    
327      /**
328       * Returns a bounding box for this shape, in integer format. Notice that you
329       * may get a tighter bound with getBounds2D. If the frame is empty, the
330       * box is the default empty box at the origin.
331       *
332       * @return a bounding box
333       */
334      public Rectangle getBounds()
335      {
336        if (isEmpty())
337          return new Rectangle();
338        double x = getX();
339        double y = getY();
340        double maxx = Math.ceil(x + getWidth());
341        double maxy = Math.ceil(y + getHeight());
342        x = Math.floor(x);
343        y = Math.floor(y);
344        return new Rectangle((int) x, (int) y, (int) (maxx - x), (int) (maxy - y));
345      }
346    
347      /**
348       * Return an iterator along the shape boundary. If the optional transform
349       * is provided, the iterator is transformed accordingly. The path is
350       * flattened until all segments differ from the curve by at most the value
351       * of the flatness parameter, within the limits of the default interpolation
352       * recursion limit of 1024 segments between actual points. Each call
353       * returns a new object, independent from others in use. The result is
354       * threadsafe if and only if the iterator returned by
355       * {@link #getPathIterator(AffineTransform)} is as well.
356       *
357       * @param transform an optional transform to apply to the iterator
358       * @param flatness the desired flatness
359       * @return a new iterator over the boundary
360       * @throws IllegalArgumentException if flatness is invalid
361       * @since 1.2
362       */
363      public PathIterator getPathIterator(AffineTransform at, double flatness)
364      {
365        return new FlatteningPathIterator(getPathIterator(at), flatness);
366      }
367    
368      /**
369       * Create a new shape of the same run-time type with the same contents as
370       * this one.
371       *
372       * @return the clone
373       */
374      public Object clone()
375    {    {
376      try      try
377      {        {
378        return super.clone ();          return super.clone();
379      }        }
380      catch (CloneNotSupportedException _) {return null;}      catch (CloneNotSupportedException e)
381    }        {
382            throw (Error) new InternalError().initCause(e); // Impossible
383    // This implements the PathIterator for all RectangularShape objects        }
   // that don't override getPathIterator.  
   private class Iterator implements PathIterator  
   {  
     // Our current coordinate.  
     private int coord;  
   
     private static final int START = 0;  
     private static final int END_PLUS_ONE = 5;  
   
     public Iterator ()  
     {  
       coord = START;  
     }  
   
     public int currentSegment (double[] coords)  
     {  
       int r;  
       switch (coord)  
         {  
         case 0:  
           coords[0] = getX ();  
           coords[1] = getY ();  
           r = SEG_MOVETO;  
           break;  
   
         case 1:  
           coords[0] = getX () + getWidth ();  
           coords[1] = getY ();  
           r = SEG_LINETO;  
           break;  
   
         case 2:  
           coords[0] = getX () + getWidth ();  
           coords[1] = getY () + getHeight ();  
           r = SEG_LINETO;  
           break;  
   
         case 3:  
           coords[0] = getX ();  
           coords[1] = getY () + getHeight ();  
           r = SEG_LINETO;  
           break;  
   
         case 4:  
           r = SEG_CLOSE;  
           break;            
   
         default:  
           // It isn't clear what to do if the caller calls us after  
           // isDone returns true.  
           r = SEG_CLOSE;  
           break;  
         }  
   
       return r;  
     }  
   
     public int currentSegment (float[] coords)  
     {  
       int r;  
       switch (coord)  
         {  
         case 0:  
           coords[0] = (float) getX ();  
           coords[1] = (float) getY ();  
           r = SEG_MOVETO;  
           break;  
   
         case 1:  
           coords[0] = (float) (getX () + getWidth ());  
           coords[1] = (float) getY ();  
           r = SEG_LINETO;  
           break;  
   
         case 2:  
           coords[0] = (float) (getX () + getWidth ());  
           coords[1] = (float) (getY () + getHeight ());  
           r = SEG_LINETO;  
           break;  
   
         case 3:  
           coords[0] = (float) getX ();  
           coords[1] = (float) (getY () + getHeight ());  
           r = SEG_LINETO;  
           break;  
   
         case 4:  
         default:  
           // It isn't clear what to do if the caller calls us after  
           // isDone returns true.  We elect to keep returning  
           // SEG_CLOSE.  
           r = SEG_CLOSE;  
           break;            
         }  
   
       return r;  
     }  
   
     public int getWindingRule ()  
     {  
       return WIND_NON_ZERO;  
     }  
   
     public boolean isDone ()  
     {  
       return coord == END_PLUS_ONE;  
     }  
   
     public void next ()  
     {  
       if (coord < END_PLUS_ONE)  
         ++coord;  
     }  
384    }    }
385  }  } // class RectangularShape

Legend:
Removed from v.1.2  
changed lines
  Added in v.1.3

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26