1/* 2 * Copyright (c) 1997, 2006, Oracle and/or its affiliates. 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package java.awt.geom; 27 28import java.io.Serializable; 29 30/** 31 * The {@code Ellipse2D} 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} class defines an ellipse specified 46 * in {@code float} 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}. 68 * @since 1.2 69 * @serial 70 */ 71 public float width; 72 73 /** 74 * The overall height of this {@code Ellipse2D}. 75 * @since 1.2 76 * @serial 77 */ 78 public float height; 79 80 /** 81 * Constructs a new {@code Ellipse2D}, initialized to 82 * location (0, 0) and size (0, 0). 83 * @since 1.2 84 */ 85 public Float() { 86 } 87 88 /** 89 * Constructs and initializes an {@code Ellipse2D} 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} 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} class defines an ellipse specified 190 * in {@code double} 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}. 212 * @since 1.2 213 * @serial 214 */ 215 public double width; 216 217 /** 218 * The overall height of the {@code Ellipse2D}. 219 * @since 1.2 220 * @serial 221 */ 222 public double height; 223 224 /** 225 * Constructs a new {@code Ellipse2D}, initialized to 226 * location (0, 0) and size (0, 0). 227 * @since 1.2 228 */ 229 public Double() { 230 } 231 232 /** 233 * Constructs and initializes an {@code Ellipse2D} 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}. 408 * The iterator for this class is multi-threaded safe, which means 409 * that this {@code Ellipse2D} class guarantees that 410 * modifications to the geometry of this {@code Ellipse2D} 411 * object do not affect any iterations of that geometry that 412 * are already in process. 413 * @param at an optional {@code AffineTransform} to be applied to 414 * the coordinates as they are returned in the iteration, or 415 * {@code null} if untransformed coordinates are desired 416 * @return the {@code PathIterator} object that returns the 417 * geometry of the outline of this {@code Ellipse2D}, 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}. 427 * @return the hashcode for this {@code Ellipse2D}. 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} is 440 * equal to this {@code Ellipse2D}. The specified 441 * {@code Object} is equal to this {@code Ellipse2D} 442 * if it is an instance of {@code Ellipse2D} and if its 443 * location and size are the same as this {@code Ellipse2D}. 444 * @param obj an {@code Object} to be compared with this 445 * {@code Ellipse2D}. 446 * @return {@code true} if {@code obj} is an instance 447 * of {@code Ellipse2D} and has the same values; 448 * {@code false} 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} 465