blob: 39e01c25e236d33aa5d19d94598c5d9a5d5de627 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package java.awt.geom;
27
28import java.io.Serializable;
29
30/**
31 * The <code>Ellipse2D</code> class describes an ellipse that is defined
32 * by a framing rectangle.
33 * <p>
34 * This class is only the abstract superclass for all objects which
35 * store a 2D ellipse.
36 * The actual storage representation of the coordinates is left to
37 * the subclass.
38 *
39 * @author Jim Graham
40 * @since 1.2
41 */
42public abstract class Ellipse2D extends RectangularShape {
43
44 /**
45 * The <code>Float</code> class defines an ellipse specified
46 * in <code>float</code> precision.
47 * @since 1.2
48 */
49 public static class Float extends Ellipse2D implements Serializable {
50 /**
51 * The X coordinate of the upper-left corner of the
52 * framing rectangle of this {@code Ellipse2D}.
53 * @since 1.2
54 * @serial
55 */
56 public float x;
57
58 /**
59 * The Y coordinate of the upper-left corner of the
60 * framing rectangle of this {@code Ellipse2D}.
61 * @since 1.2
62 * @serial
63 */
64 public float y;
65
66 /**
67 * The overall width of this <code>Ellipse2D</code>.
68 * @since 1.2
69 * @serial
70 */
71 public float width;
72
73 /**
74 * The overall height of this <code>Ellipse2D</code>.
75 * @since 1.2
76 * @serial
77 */
78 public float height;
79
80 /**
81 * Constructs a new <code>Ellipse2D</code>, initialized to
82 * location (0,&nbsp;0) and size (0,&nbsp;0).
83 * @since 1.2
84 */
85 public Float() {
86 }
87
88 /**
89 * Constructs and initializes an <code>Ellipse2D</code> from the
90 * specified coordinates.
91 *
92 * @param x the X coordinate of the upper-left corner
93 * of the framing rectangle
94 * @param y the Y coordinate of the upper-left corner
95 * of the framing rectangle
96 * @param w the width of the framing rectangle
97 * @param h the height of the framing rectangle
98 * @since 1.2
99 */
100 public Float(float x, float y, float w, float h) {
101 setFrame(x, y, w, h);
102 }
103
104 /**
105 * {@inheritDoc}
106 * @since 1.2
107 */
108 public double getX() {
109 return (double) x;
110 }
111
112 /**
113 * {@inheritDoc}
114 * @since 1.2
115 */
116 public double getY() {
117 return (double) y;
118 }
119
120 /**
121 * {@inheritDoc}
122 * @since 1.2
123 */
124 public double getWidth() {
125 return (double) width;
126 }
127
128 /**
129 * {@inheritDoc}
130 * @since 1.2
131 */
132 public double getHeight() {
133 return (double) height;
134 }
135
136 /**
137 * {@inheritDoc}
138 * @since 1.2
139 */
140 public boolean isEmpty() {
141 return (width <= 0.0 || height <= 0.0);
142 }
143
144 /**
145 * Sets the location and size of the framing rectangle of this
146 * <code>Shape</code> to the specified rectangular values.
147 *
148 * @param x the X coordinate of the upper-left corner of the
149 * specified rectangular shape
150 * @param y the Y coordinate of the upper-left corner of the
151 * specified rectangular shape
152 * @param w the width of the specified rectangular shape
153 * @param h the height of the specified rectangular shape
154 * @since 1.2
155 */
156 public void setFrame(float x, float y, float w, float h) {
157 this.x = x;
158 this.y = y;
159 this.width = w;
160 this.height = h;
161 }
162
163 /**
164 * {@inheritDoc}
165 * @since 1.2
166 */
167 public void setFrame(double x, double y, double w, double h) {
168 this.x = (float) x;
169 this.y = (float) y;
170 this.width = (float) w;
171 this.height = (float) h;
172 }
173
174 /**
175 * {@inheritDoc}
176 * @since 1.2
177 */
178 public Rectangle2D getBounds2D() {
179 return new Rectangle2D.Float(x, y, width, height);
180 }
181
182 /*
183 * JDK 1.6 serialVersionUID
184 */
185 private static final long serialVersionUID = -6633761252372475977L;
186 }
187
188 /**
189 * The <code>Double</code> class defines an ellipse specified
190 * in <code>double</code> precision.
191 * @since 1.2
192 */
193 public static class Double extends Ellipse2D implements Serializable {
194 /**
195 * The X coordinate of the upper-left corner of the
196 * framing rectangle of this {@code Ellipse2D}.
197 * @since 1.2
198 * @serial
199 */
200 public double x;
201
202 /**
203 * The Y coordinate of the upper-left corner of the
204 * framing rectangle of this {@code Ellipse2D}.
205 * @since 1.2
206 * @serial
207 */
208 public double y;
209
210 /**
211 * The overall width of this <code>Ellipse2D</code>.
212 * @since 1.2
213 * @serial
214 */
215 public double width;
216
217 /**
218 * The overall height of the <code>Ellipse2D</code>.
219 * @since 1.2
220 * @serial
221 */
222 public double height;
223
224 /**
225 * Constructs a new <code>Ellipse2D</code>, initialized to
226 * location (0,&nbsp;0) and size (0,&nbsp;0).
227 * @since 1.2
228 */
229 public Double() {
230 }
231
232 /**
233 * Constructs and initializes an <code>Ellipse2D</code> from the
234 * specified coordinates.
235 *
236 * @param x the X coordinate of the upper-left corner
237 * of the framing rectangle
238 * @param y the Y coordinate of the upper-left corner
239 * of the framing rectangle
240 * @param w the width of the framing rectangle
241 * @param h the height of the framing rectangle
242 * @since 1.2
243 */
244 public Double(double x, double y, double w, double h) {
245 setFrame(x, y, w, h);
246 }
247
248 /**
249 * {@inheritDoc}
250 * @since 1.2
251 */
252 public double getX() {
253 return x;
254 }
255
256 /**
257 * {@inheritDoc}
258 * @since 1.2
259 */
260 public double getY() {
261 return y;
262 }
263
264 /**
265 * {@inheritDoc}
266 * @since 1.2
267 */
268 public double getWidth() {
269 return width;
270 }
271
272 /**
273 * {@inheritDoc}
274 * @since 1.2
275 */
276 public double getHeight() {
277 return height;
278 }
279
280 /**
281 * {@inheritDoc}
282 * @since 1.2
283 */
284 public boolean isEmpty() {
285 return (width <= 0.0 || height <= 0.0);
286 }
287
288 /**
289 * {@inheritDoc}
290 * @since 1.2
291 */
292 public void setFrame(double x, double y, double w, double h) {
293 this.x = x;
294 this.y = y;
295 this.width = w;
296 this.height = h;
297 }
298
299 /**
300 * {@inheritDoc}
301 * @since 1.2
302 */
303 public Rectangle2D getBounds2D() {
304 return new Rectangle2D.Double(x, y, width, height);
305 }
306
307 /*
308 * JDK 1.6 serialVersionUID
309 */
310 private static final long serialVersionUID = 5555464816372320683L;
311 }
312
313 /**
314 * This is an abstract class that cannot be instantiated directly.
315 * Type-specific implementation subclasses are available for
316 * instantiation and provide a number of formats for storing
317 * the information necessary to satisfy the various accessor
318 * methods below.
319 *
320 * @see java.awt.geom.Ellipse2D.Float
321 * @see java.awt.geom.Ellipse2D.Double
322 * @since 1.2
323 */
324 protected Ellipse2D() {
325 }
326
327 /**
328 * {@inheritDoc}
329 * @since 1.2
330 */
331 public boolean contains(double x, double y) {
332 // Normalize the coordinates compared to the ellipse
333 // having a center at 0,0 and a radius of 0.5.
334 double ellw = getWidth();
335 if (ellw <= 0.0) {
336 return false;
337 }
338 double normx = (x - getX()) / ellw - 0.5;
339 double ellh = getHeight();
340 if (ellh <= 0.0) {
341 return false;
342 }
343 double normy = (y - getY()) / ellh - 0.5;
344 return (normx * normx + normy * normy) < 0.25;
345 }
346
347 /**
348 * {@inheritDoc}
349 * @since 1.2
350 */
351 public boolean intersects(double x, double y, double w, double h) {
352 if (w <= 0.0 || h <= 0.0) {
353 return false;
354 }
355 // Normalize the rectangular coordinates compared to the ellipse
356 // having a center at 0,0 and a radius of 0.5.
357 double ellw = getWidth();
358 if (ellw <= 0.0) {
359 return false;
360 }
361 double normx0 = (x - getX()) / ellw - 0.5;
362 double normx1 = normx0 + w / ellw;
363 double ellh = getHeight();
364 if (ellh <= 0.0) {
365 return false;
366 }
367 double normy0 = (y - getY()) / ellh - 0.5;
368 double normy1 = normy0 + h / ellh;
369 // find nearest x (left edge, right edge, 0.0)
370 // find nearest y (top edge, bottom edge, 0.0)
371 // if nearest x,y is inside circle of radius 0.5, then intersects
372 double nearx, neary;
373 if (normx0 > 0.0) {
374 // center to left of X extents
375 nearx = normx0;
376 } else if (normx1 < 0.0) {
377 // center to right of X extents
378 nearx = normx1;
379 } else {
380 nearx = 0.0;
381 }
382 if (normy0 > 0.0) {
383 // center above Y extents
384 neary = normy0;
385 } else if (normy1 < 0.0) {
386 // center below Y extents
387 neary = normy1;
388 } else {
389 neary = 0.0;
390 }
391 return (nearx * nearx + neary * neary) < 0.25;
392 }
393
394 /**
395 * {@inheritDoc}
396 * @since 1.2
397 */
398 public boolean contains(double x, double y, double w, double h) {
399 return (contains(x, y) &&
400 contains(x + w, y) &&
401 contains(x, y + h) &&
402 contains(x + w, y + h));
403 }
404
405 /**
406 * Returns an iteration object that defines the boundary of this
407 * <code>Ellipse2D</code>.
408 * The iterator for this class is multi-threaded safe, which means
409 * that this <code>Ellipse2D</code> class guarantees that
410 * modifications to the geometry of this <code>Ellipse2D</code>
411 * object do not affect any iterations of that geometry that
412 * are already in process.
413 * @param at an optional <code>AffineTransform</code> to be applied to
414 * the coordinates as they are returned in the iteration, or
415 * <code>null</code> if untransformed coordinates are desired
416 * @return the <code>PathIterator</code> object that returns the
417 * geometry of the outline of this <code>Ellipse2D</code>,
418 * one segment at a time.
419 * @since 1.2
420 */
421 public PathIterator getPathIterator(AffineTransform at) {
422 return new EllipseIterator(this, at);
423 }
424
425 /**
426 * Returns the hashcode for this <code>Ellipse2D</code>.
427 * @return the hashcode for this <code>Ellipse2D</code>.
428 * @since 1.6
429 */
430 public int hashCode() {
431 long bits = java.lang.Double.doubleToLongBits(getX());
432 bits += java.lang.Double.doubleToLongBits(getY()) * 37;
433 bits += java.lang.Double.doubleToLongBits(getWidth()) * 43;
434 bits += java.lang.Double.doubleToLongBits(getHeight()) * 47;
435 return (((int) bits) ^ ((int) (bits >> 32)));
436 }
437
438 /**
439 * Determines whether or not the specified <code>Object</code> is
440 * equal to this <code>Ellipse2D</code>. The specified
441 * <code>Object</code> is equal to this <code>Ellipse2D</code>
442 * if it is an instance of <code>Ellipse2D</code> and if its
443 * location and size are the same as this <code>Ellipse2D</code>.
444 * @param obj an <code>Object</code> to be compared with this
445 * <code>Ellipse2D</code>.
446 * @return <code>true</code> if <code>obj</code> is an instance
447 * of <code>Ellipse2D</code> and has the same values;
448 * <code>false</code> otherwise.
449 * @since 1.6
450 */
451 public boolean equals(Object obj) {
452 if (obj == this) {
453 return true;
454 }
455 if (obj instanceof Ellipse2D) {
456 Ellipse2D e2d = (Ellipse2D) obj;
457 return ((getX() == e2d.getX()) &&
458 (getY() == e2d.getY()) &&
459 (getWidth() == e2d.getWidth()) &&
460 (getHeight() == e2d.getHeight()));
461 }
462 return false;
463 }
464}