001 /*
002 * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package java.awt.geom;
027
028 import java.io.Serializable;
029
030 /**
031 * The <code>Ellipse2D</code> class describes an ellipse that is defined
032 * by a framing rectangle.
033 * <p>
034 * This class is only the abstract superclass for all objects which
035 * store a 2D ellipse.
036 * The actual storage representation of the coordinates is left to
037 * the subclass.
038 *
039 * @version 1.26, 05/05/07
040 * @author Jim Graham
041 * @since 1.2
042 */
043 public abstract class Ellipse2D extends RectangularShape {
044
045 /**
046 * The <code>Float</code> class defines an ellipse specified
047 * in <code>float</code> precision.
048 * @since 1.2
049 */
050 public static class Float extends Ellipse2D implements Serializable {
051 /**
052 * The X coordinate of the upper-left corner of the
053 * framing rectangle of this {@code Ellipse2D}.
054 * @since 1.2
055 * @serial
056 */
057 public float x;
058
059 /**
060 * The Y coordinate of the upper-left corner of the
061 * framing rectangle of this {@code Ellipse2D}.
062 * @since 1.2
063 * @serial
064 */
065 public float y;
066
067 /**
068 * The overall width of this <code>Ellipse2D</code>.
069 * @since 1.2
070 * @serial
071 */
072 public float width;
073
074 /**
075 * The overall height of this <code>Ellipse2D</code>.
076 * @since 1.2
077 * @serial
078 */
079 public float height;
080
081 /**
082 * Constructs a new <code>Ellipse2D</code>, initialized to
083 * location (0, 0) and size (0, 0).
084 * @since 1.2
085 */
086 public Float() {
087 }
088
089 /**
090 * Constructs and initializes an <code>Ellipse2D</code> from the
091 * specified coordinates.
092 *
093 * @param x the X coordinate of the upper-left corner
094 * of the framing rectangle
095 * @param y the Y coordinate of the upper-left corner
096 * of the framing rectangle
097 * @param w the width of the framing rectangle
098 * @param h the height of the framing rectangle
099 * @since 1.2
100 */
101 public Float(float x, float y, float w, float h) {
102 setFrame(x, y, w, h);
103 }
104
105 /**
106 * {@inheritDoc}
107 * @since 1.2
108 */
109 public double getX() {
110 return (double) x;
111 }
112
113 /**
114 * {@inheritDoc}
115 * @since 1.2
116 */
117 public double getY() {
118 return (double) y;
119 }
120
121 /**
122 * {@inheritDoc}
123 * @since 1.2
124 */
125 public double getWidth() {
126 return (double) width;
127 }
128
129 /**
130 * {@inheritDoc}
131 * @since 1.2
132 */
133 public double getHeight() {
134 return (double) height;
135 }
136
137 /**
138 * {@inheritDoc}
139 * @since 1.2
140 */
141 public boolean isEmpty() {
142 return (width <= 0.0 || height <= 0.0);
143 }
144
145 /**
146 * Sets the location and size of the framing rectangle of this
147 * <code>Shape</code> to the specified rectangular values.
148 *
149 * @param x the X coordinate of the upper-left corner of the
150 * specified rectangular shape
151 * @param y the Y coordinate of the upper-left corner of the
152 * specified rectangular shape
153 * @param w the width of the specified rectangular shape
154 * @param h the height of the specified rectangular shape
155 * @since 1.2
156 */
157 public void setFrame(float x, float y, float w, float h) {
158 this .x = x;
159 this .y = y;
160 this .width = w;
161 this .height = h;
162 }
163
164 /**
165 * {@inheritDoc}
166 * @since 1.2
167 */
168 public void setFrame(double x, double y, double w, double h) {
169 this .x = (float) x;
170 this .y = (float) y;
171 this .width = (float) w;
172 this .height = (float) h;
173 }
174
175 /**
176 * {@inheritDoc}
177 * @since 1.2
178 */
179 public Rectangle2D getBounds2D() {
180 return new Rectangle2D.Float(x, y, width, height);
181 }
182
183 /*
184 * JDK 1.6 serialVersionUID
185 */
186 private static final long serialVersionUID = -6633761252372475977L;
187 }
188
189 /**
190 * The <code>Double</code> class defines an ellipse specified
191 * in <code>double</code> precision.
192 * @since 1.2
193 */
194 public static class Double extends Ellipse2D implements
195 Serializable {
196 /**
197 * The X coordinate of the upper-left corner of the
198 * framing rectangle of this {@code Ellipse2D}.
199 * @since 1.2
200 * @serial
201 */
202 public double x;
203
204 /**
205 * The Y coordinate of the upper-left corner of the
206 * framing rectangle of this {@code Ellipse2D}.
207 * @since 1.2
208 * @serial
209 */
210 public double y;
211
212 /**
213 * The overall width of this <code>Ellipse2D</code>.
214 * @since 1.2
215 * @serial
216 */
217 public double width;
218
219 /**
220 * The overall height of the <code>Ellipse2D</code>.
221 * @since 1.2
222 * @serial
223 */
224 public double height;
225
226 /**
227 * Constructs a new <code>Ellipse2D</code>, initialized to
228 * location (0, 0) and size (0, 0).
229 * @since 1.2
230 */
231 public Double() {
232 }
233
234 /**
235 * Constructs and initializes an <code>Ellipse2D</code> from the
236 * specified coordinates.
237 *
238 * @param x the X coordinate of the upper-left corner
239 * of the framing rectangle
240 * @param y the Y coordinate of the upper-left corner
241 * of the framing rectangle
242 * @param w the width of the framing rectangle
243 * @param h the height of the framing rectangle
244 * @since 1.2
245 */
246 public Double(double x, double y, double w, double h) {
247 setFrame(x, y, w, h);
248 }
249
250 /**
251 * {@inheritDoc}
252 * @since 1.2
253 */
254 public double getX() {
255 return x;
256 }
257
258 /**
259 * {@inheritDoc}
260 * @since 1.2
261 */
262 public double getY() {
263 return y;
264 }
265
266 /**
267 * {@inheritDoc}
268 * @since 1.2
269 */
270 public double getWidth() {
271 return width;
272 }
273
274 /**
275 * {@inheritDoc}
276 * @since 1.2
277 */
278 public double getHeight() {
279 return height;
280 }
281
282 /**
283 * {@inheritDoc}
284 * @since 1.2
285 */
286 public boolean isEmpty() {
287 return (width <= 0.0 || height <= 0.0);
288 }
289
290 /**
291 * {@inheritDoc}
292 * @since 1.2
293 */
294 public void setFrame(double x, double y, double w, double h) {
295 this .x = x;
296 this .y = y;
297 this .width = w;
298 this .height = h;
299 }
300
301 /**
302 * {@inheritDoc}
303 * @since 1.2
304 */
305 public Rectangle2D getBounds2D() {
306 return new Rectangle2D.Double(x, y, width, height);
307 }
308
309 /*
310 * JDK 1.6 serialVersionUID
311 */
312 private static final long serialVersionUID = 5555464816372320683L;
313 }
314
315 /**
316 * This is an abstract class that cannot be instantiated directly.
317 * Type-specific implementation subclasses are available for
318 * instantiation and provide a number of formats for storing
319 * the information necessary to satisfy the various accessor
320 * methods below.
321 *
322 * @see java.awt.geom.Ellipse2D.Float
323 * @see java.awt.geom.Ellipse2D.Double
324 * @since 1.2
325 */
326 protected Ellipse2D() {
327 }
328
329 /**
330 * {@inheritDoc}
331 * @since 1.2
332 */
333 public boolean contains(double x, double y) {
334 // Normalize the coordinates compared to the ellipse
335 // having a center at 0,0 and a radius of 0.5.
336 double ellw = getWidth();
337 if (ellw <= 0.0) {
338 return false;
339 }
340 double normx = (x - getX()) / ellw - 0.5;
341 double ellh = getHeight();
342 if (ellh <= 0.0) {
343 return false;
344 }
345 double normy = (y - getY()) / ellh - 0.5;
346 return (normx * normx + normy * normy) < 0.25;
347 }
348
349 /**
350 * {@inheritDoc}
351 * @since 1.2
352 */
353 public boolean intersects(double x, double y, double w, double h) {
354 if (w <= 0.0 || h <= 0.0) {
355 return false;
356 }
357 // Normalize the rectangular coordinates compared to the ellipse
358 // having a center at 0,0 and a radius of 0.5.
359 double ellw = getWidth();
360 if (ellw <= 0.0) {
361 return false;
362 }
363 double normx0 = (x - getX()) / ellw - 0.5;
364 double normx1 = normx0 + w / ellw;
365 double ellh = getHeight();
366 if (ellh <= 0.0) {
367 return false;
368 }
369 double normy0 = (y - getY()) / ellh - 0.5;
370 double normy1 = normy0 + h / ellh;
371 // find nearest x (left edge, right edge, 0.0)
372 // find nearest y (top edge, bottom edge, 0.0)
373 // if nearest x,y is inside circle of radius 0.5, then intersects
374 double nearx, neary;
375 if (normx0 > 0.0) {
376 // center to left of X extents
377 nearx = normx0;
378 } else if (normx1 < 0.0) {
379 // center to right of X extents
380 nearx = normx1;
381 } else {
382 nearx = 0.0;
383 }
384 if (normy0 > 0.0) {
385 // center above Y extents
386 neary = normy0;
387 } else if (normy1 < 0.0) {
388 // center below Y extents
389 neary = normy1;
390 } else {
391 neary = 0.0;
392 }
393 return (nearx * nearx + neary * neary) < 0.25;
394 }
395
396 /**
397 * {@inheritDoc}
398 * @since 1.2
399 */
400 public boolean contains(double x, double y, double w, double h) {
401 return (contains(x, y) && contains(x + w, y)
402 && contains(x, y + h) && 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()) && (getY() == e2d.getY())
458 && (getWidth() == e2d.getWidth()) && (getHeight() == e2d
459 .getHeight()));
460 }
461 return false;
462 }
463 }
|