001/* Ellipse2D.java -- represents an ellipse in 2-D space
002   Copyright (C) 2000, 2002, 2004 Free Software Foundation
003
004This file is part of GNU Classpath.
005
006GNU Classpath is free software; you can redistribute it and/or modify
007it under the terms of the GNU General Public License as published by
008the Free Software Foundation; either version 2, or (at your option)
009any later version.
010
011GNU Classpath is distributed in the hope that it will be useful, but
012WITHOUT ANY WARRANTY; without even the implied warranty of
013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014General Public License for more details.
015
016You should have received a copy of the GNU General Public License
017along with GNU Classpath; see the file COPYING.  If not, write to the
018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
01902110-1301 USA.
020
021Linking this library statically or dynamically with other modules is
022making a combined work based on this library.  Thus, the terms and
023conditions of the GNU General Public License cover the whole
024combination.
025
026As a special exception, the copyright holders of this library give you
027permission to link this library with independent modules to produce an
028executable, regardless of the license terms of these independent
029modules, and to copy and distribute the resulting executable under
030terms of your choice, provided that you also meet, for each linked
031independent module, the terms and conditions of the license of that
032module.  An independent module is a module which is not derived from
033or based on this library.  If you modify this library, you may extend
034this exception to your version of the library, but you are not
035obligated to do so.  If you do not wish to do so, delete this
036exception statement from your version. */
037
038package 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 */
056public 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