001    /* Ellipse2D.java -- represents an ellipse in 2-D space
002       Copyright (C) 2000, 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    package java.awt.geom;
039    
040    
041    /**
042     * Ellipse2D is the shape of an ellipse.
043     * <BR>
044     * <img src="doc-files/Ellipse-1.png" width="347" height="221"
045     * alt="A drawing of an ellipse" /><BR>
046     * The ellipse is defined by it's bounding box (shown in red),
047     * and is defined by the implicit curve:<BR>
048     * <blockquote>(<i>x</i>/<i>a</i>)<sup>2</sup> +
049     * (<i>y</i>/<i>b</i>)<sup>2</sup> = 1<BR><BR></blockquote>
050     *
051     * @author Tom Tromey (tromey@cygnus.com)
052     * @author Eric Blake (ebb9@email.byu.edu)
053     *
054     * @since 1.2
055     */
056    public abstract class Ellipse2D extends RectangularShape
057    {
058      /**
059       * Ellipse2D is defined as abstract.
060       * Implementing classes are Ellipse2D.Float and Ellipse2D.Double.
061       */
062      protected Ellipse2D()
063      {
064      }
065    
066      /**
067       * Determines if a point is contained within the ellipse. <P>
068       * @param x - x coordinate of the point.
069       * @param y - y coordinate of the point.
070       * @return true if the point is within the ellipse, false otherwise.
071       */
072      public boolean contains(double x, double y)
073      {
074        double rx = getWidth() / 2;
075        double ry = getHeight() / 2;
076        double tx = (x - (getX() + rx)) / rx;
077        double ty = (y - (getY() + ry)) / ry;
078        return tx * tx + ty * ty < 1.0;
079      }
080    
081      /**
082       * Determines if a rectangle is completely contained within the
083       * ellipse. <P>
084       * @param x - x coordinate of the upper-left corner of the rectangle
085       * @param y - y coordinate of the upper-left corner of the rectangle
086       * @param w - width of the rectangle
087       * @param h - height of the rectangle
088       * @return true if the rectangle is completely contained, false otherwise.
089       */
090      public boolean contains(double x, double y, double w, double h)
091      {
092        double x2 = x + w;
093        double y2 = y + h;
094        return (contains(x, y) && contains(x, y2) && contains(x2, y)
095               && contains(x2, y2));
096      }
097    
098      /**
099       * Returns a PathIterator object corresponding to the ellipse.<P>
100       *
101       * Note: An ellipse cannot be represented exactly in PathIterator
102       * segments, the outline is thefore approximated with cubic
103       * Bezier segments.
104       * 
105       * @param at an optional transform.
106       * @return A path iterator.
107       */
108      public PathIterator getPathIterator(AffineTransform at)
109      {
110        // An ellipse is just a complete arc.
111        return new Arc2D.ArcIterator(this, at);
112      }
113    
114      /**
115       * Determines if a rectangle intersects any part of the ellipse.<P>
116       * @param x - x coordinate of the upper-left corner of the rectangle
117       * @param y - y coordinate of the upper-left corner of the rectangle
118       * @param w - width of the rectangle
119       * @param h - height of the rectangle
120       * @return true if the rectangle intersects the ellipse, false otherwise.
121       */
122      public boolean intersects(double x, double y, double w, double h)
123      {
124        Rectangle2D r = new Rectangle2D.Double(x, y, w, h);
125        if (! r.intersects(getX(), getY(), getWidth(), getHeight()))
126          return false;
127    
128        if (contains(x, y) || contains(x, y + h) || contains(x + w, y)
129            || contains(x + w, y + h))
130          return true;
131    
132        Line2D l1 = new Line2D.Double(getX(), getY() + (getHeight() / 2),
133                                      getX() + getWidth(),
134                                      getY() + (getHeight() / 2));
135        Line2D l2 = new Line2D.Double(getX() + (getWidth() / 2), getY(),
136                                      getX() + (getWidth() / 2),
137                                      getY() + getHeight());
138    
139        if (l1.intersects(r) || l2.intersects(r))
140          return true;
141    
142        return false;
143      }
144    
145      /**
146       * An {@link Ellipse2D} that stores its coordinates using <code>double</code>
147       * primitives.
148       */
149      public static class Double extends Ellipse2D
150      {
151        /**
152         * The height of the ellipse.
153         */
154        public double height;
155    
156        /**
157         * The width of the ellipse.
158         */
159        public double width;
160    
161        /**
162         * The upper-left x coordinate of the bounding-box
163         */
164        public double x;
165    
166        /**
167         * The upper-left y coordinate of the bounding-box
168         */
169        public double y;
170    
171        /**
172         * Creates a new Ellipse2D with an upper-left coordinate of (0,0)
173         * and a zero size.
174         */
175        public Double()
176        {
177        }
178    
179        /**
180         * Creates a new Ellipse2D within a given rectangle
181         * using double-precision coordinates.<P>
182         * @param x - x coordinate of the upper-left of the bounding rectangle
183         * @param y - y coordinate of the upper-left of the bounding rectangle
184         * @param w - width of the ellipse
185         * @param h - height of the ellipse
186         */
187        public Double(double x, double y, double w, double h)
188        {
189          this.x = x;
190          this.y = y;
191          height = h;
192          width = w;
193        }
194    
195        /**
196         * Returns the bounding-box of the ellipse.
197         * @return The bounding box.
198         */
199        public Rectangle2D getBounds2D()
200        {
201          return new Rectangle2D.Double(x, y, width, height);
202        }
203    
204        /**
205         * Returns the height of the ellipse.
206         * @return The height of the ellipse.
207         */
208        public double getHeight()
209        {
210          return height;
211        }
212    
213        /**
214         * Returns the width of the ellipse.
215         * @return The width of the ellipse.
216         */
217        public double getWidth()
218        {
219          return width;
220        }
221    
222        /**
223         * Returns x coordinate of the upper-left corner of
224         * the ellipse's bounding-box.
225         * @return The x coordinate.
226         */
227        public double getX()
228        {
229          return x;
230        }
231    
232        /**
233         * Returns y coordinate of the upper-left corner of
234         * the ellipse's bounding-box.
235         * @return The y coordinate.
236         */
237        public double getY()
238        {
239          return y;
240        }
241    
242        /**
243         * Returns <code>true</code> if the ellipse encloses no area, and
244         * <code>false</code> otherwise.
245         * 
246         * @return A boolean.
247         */
248        public boolean isEmpty()
249        {
250          return height <= 0 || width <= 0;
251        }
252    
253        /**
254         * Sets the geometry of the ellipse's bounding box.<P>
255         *
256         * @param x - x coordinate of the upper-left of the bounding rectangle
257         * @param y - y coordinate of the upper-left of the bounding rectangle
258         * @param w - width of the ellipse
259         * @param h - height of the ellipse
260         */
261        public void setFrame(double x, double y, double w, double h)
262        {
263          this.x = x;
264          this.y = y;
265          height = h;
266          width = w;
267        }
268      } // class Double
269    
270      /**
271       * An {@link Ellipse2D} that stores its coordinates using <code>float</code>
272       * primitives.
273       */
274      public static class Float extends Ellipse2D
275      {
276        /**
277         * The height of the ellipse.
278         */
279        public float height;
280    
281        /**
282         * The width of the ellipse.
283         */
284        public float width;
285    
286        /**
287         * The upper-left x coordinate of the bounding-box
288         */
289        public float x;
290    
291        /**
292         * The upper-left y coordinate of the bounding-box
293         */
294        public float y;
295    
296        /**
297         * Creates a new Ellipse2D with an upper-left coordinate of (0,0)
298         * and a zero size.
299         */
300        public Float()
301        {
302        }
303    
304        /**
305         * Creates a new Ellipse2D within a given rectangle
306         * using floating-point precision.<P>
307         * @param x - x coordinate of the upper-left of the bounding rectangle
308         * @param y - y coordinate of the upper-left of the bounding rectangle
309         * @param w - width of the ellipse
310         * @param h - height of the ellipse
311         *
312         */
313        public Float(float x, float y, float w, float h)
314        {
315          this.x = x;
316          this.y = y;
317          this.height = h;
318          this.width = w;
319        }
320    
321        /**
322         * Returns the bounding-box of the ellipse.
323         * @return The bounding box.
324         */
325        public Rectangle2D getBounds2D()
326        {
327          return new Rectangle2D.Float(x, y, width, height);
328        }
329    
330        /**
331         * Returns the height of the ellipse.
332         * @return The height of the ellipse.
333         */
334        public double getHeight()
335        {
336          return height;
337        }
338    
339        /**
340         * Returns the width of the ellipse.
341         * @return The width of the ellipse.
342         */
343        public double getWidth()
344        {
345          return width;
346        }
347    
348        /**
349         * Returns x coordinate of the upper-left corner of
350         * the ellipse's bounding-box.
351         * @return The x coordinate.
352         */
353        public double getX()
354        {
355          return x;
356        }
357    
358        /**
359         * Returns y coordinate of the upper-left corner of
360         * the ellipse's bounding-box.
361         * @return The y coordinate.
362         */
363        public double getY()
364        {
365          return y;
366        }
367    
368        /**
369         * Returns <code>true</code> if the ellipse encloses no area, and
370         * <code>false</code> otherwise.
371         * 
372         * @return A boolean.
373         */
374        public boolean isEmpty()
375        {
376          return height <= 0 || width <= 0;
377        }
378    
379        /**
380         * Sets the geometry of the ellipse's bounding box.<P>
381         *
382         * @param x - x coordinate of the upper-left of the bounding rectangle
383         * @param y - y coordinate of the upper-left of the bounding rectangle
384         * @param w - width of the ellipse
385         * @param h - height of the ellipse
386         */
387        public void setFrame(float x, float y, float w, float h)
388        {
389          this.x = x;
390          this.y = y;
391          height = h;
392          width = w;
393        }
394    
395        /**
396         * Sets the geometry of the ellipse's bounding box.
397         *
398         * Note: This leads to a loss of precision.<P>
399         *
400         * @param x - x coordinate of the upper-left of the bounding rectangle
401         * @param y - y coordinate of the upper-left of the bounding rectangle
402         * @param w - width of the ellipse
403         * @param h - height of the ellipse
404         */
405        public void setFrame(double x, double y, double w, double h)
406        {
407          this.x = (float) x;
408          this.y = (float) y;
409          height = (float) h;
410          width = (float) w;
411        }
412      } // class Float
413    } // class Ellipse2D