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