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 
  26 package java.awt.geom;
  27 
  28 import 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  */
  42 public 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 }
--- EOF ---