0001 /*
0002 * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
0003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004 *
0005 * This code is free software; you can redistribute it and/or modify it
0006 * under the terms of the GNU General Public License version 2 only, as
0007 * published by the Free Software Foundation. Sun designates this
0008 * particular file as subject to the "Classpath" exception as provided
0009 * by Sun in the LICENSE file that accompanied this code.
0010 *
0011 * This code is distributed in the hope that it will be useful, but WITHOUT
0012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0014 * version 2 for more details (a copy is included in the LICENSE file that
0015 * accompanied this code).
0016 *
0017 * You should have received a copy of the GNU General Public License version
0018 * 2 along with this work; if not, write to the Free Software Foundation,
0019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020 *
0021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022 * CA 95054 USA or visit www.sun.com if you need additional information or
0023 * have any questions.
0024 */
0025
0026 package java.awt.geom;
0027
0028 import java.io.Serializable;
0029
0030 /**
0031 * <CODE>Arc2D</CODE> is the abstract superclass for all objects that
0032 * store a 2D arc defined by a framing rectangle,
0033 * start angle, angular extent (length of the arc), and a closure type
0034 * (<CODE>OPEN</CODE>, <CODE>CHORD</CODE>, or <CODE>PIE</CODE>).
0035 * <p>
0036 * <a name="inscribes">
0037 * The arc is a partial section of a full ellipse which
0038 * inscribes the framing rectangle of its parent {@link RectangularShape}.
0039 * </a>
0040 * <a name="angles">
0041 * The angles are specified relative to the non-square
0042 * framing rectangle such that 45 degrees always falls on the line from
0043 * the center of the ellipse to the upper right corner of the framing
0044 * rectangle.
0045 * As a result, if the framing rectangle is noticeably longer along one
0046 * axis than the other, the angles to the start and end of the arc segment
0047 * will be skewed farther along the longer axis of the frame.
0048 * </a>
0049 * <p>
0050 * The actual storage representation of the coordinates is left to
0051 * the subclass.
0052 *
0053 * @version 10 Feb 1997
0054 * @author Jim Graham
0055 * @since 1.2
0056 */
0057 public abstract class Arc2D extends RectangularShape {
0058
0059 /**
0060 * The closure type for an open arc with no path segments
0061 * connecting the two ends of the arc segment.
0062 * @since 1.2
0063 */
0064 public final static int OPEN = 0;
0065
0066 /**
0067 * The closure type for an arc closed by drawing a straight
0068 * line segment from the start of the arc segment to the end of the
0069 * arc segment.
0070 * @since 1.2
0071 */
0072 public final static int CHORD = 1;
0073
0074 /**
0075 * The closure type for an arc closed by drawing straight line
0076 * segments from the start of the arc segment to the center
0077 * of the full ellipse and from that point to the end of the arc segment.
0078 * @since 1.2
0079 */
0080 public final static int PIE = 2;
0081
0082 /**
0083 * This class defines an arc specified in {@code float} precision.
0084 * @since 1.2
0085 */
0086 public static class Float extends Arc2D implements Serializable {
0087 /**
0088 * The X coordinate of the upper-left corner of the framing
0089 * rectangle of the arc.
0090 * @since 1.2
0091 * @serial
0092 */
0093 public float x;
0094
0095 /**
0096 * The Y coordinate of the upper-left corner of the framing
0097 * rectangle of the arc.
0098 * @since 1.2
0099 * @serial
0100 */
0101 public float y;
0102
0103 /**
0104 * The overall width of the full ellipse of which this arc is
0105 * a partial section (not considering the
0106 * angular extents).
0107 * @since 1.2
0108 * @serial
0109 */
0110 public float width;
0111
0112 /**
0113 * The overall height of the full ellipse of which this arc is
0114 * a partial section (not considering the
0115 * angular extents).
0116 * @since 1.2
0117 * @serial
0118 */
0119 public float height;
0120
0121 /**
0122 * The starting angle of the arc in degrees.
0123 * @since 1.2
0124 * @serial
0125 */
0126 public float start;
0127
0128 /**
0129 * The angular extent of the arc in degrees.
0130 * @since 1.2
0131 * @serial
0132 */
0133 public float extent;
0134
0135 /**
0136 * Constructs a new OPEN arc, initialized to location (0, 0),
0137 * size (0, 0), angular extents (start = 0, extent = 0).
0138 * @since 1.2
0139 */
0140 public Float() {
0141 super (OPEN);
0142 }
0143
0144 /**
0145 * Constructs a new arc, initialized to location (0, 0),
0146 * size (0, 0), angular extents (start = 0, extent = 0), and
0147 * the specified closure type.
0148 *
0149 * @param type The closure type for the arc:
0150 * {@link #OPEN}, {@link #CHORD}, or {@link #PIE}.
0151 * @since 1.2
0152 */
0153 public Float(int type) {
0154 super (type);
0155 }
0156
0157 /**
0158 * Constructs a new arc, initialized to the specified location,
0159 * size, angular extents, and closure type.
0160 *
0161 * @param x The X coordinate of the upper-left corner of
0162 * the arc's framing rectangle.
0163 * @param y The Y coordinate of the upper-left corner of
0164 * the arc's framing rectangle.
0165 * @param w The overall width of the full ellipse of which
0166 * this arc is a partial section.
0167 * @param h The overall height of the full ellipse of which this
0168 * arc is a partial section.
0169 * @param start The starting angle of the arc in degrees.
0170 * @param extent The angular extent of the arc in degrees.
0171 * @param type The closure type for the arc:
0172 * {@link #OPEN}, {@link #CHORD}, or {@link #PIE}.
0173 * @since 1.2
0174 */
0175 public Float(float x, float y, float w, float h, float start,
0176 float extent, int type) {
0177 super (type);
0178 this .x = x;
0179 this .y = y;
0180 this .width = w;
0181 this .height = h;
0182 this .start = start;
0183 this .extent = extent;
0184 }
0185
0186 /**
0187 * Constructs a new arc, initialized to the specified location,
0188 * size, angular extents, and closure type.
0189 *
0190 * @param ellipseBounds The framing rectangle that defines the
0191 * outer boundary of the full ellipse of which this arc is a
0192 * partial section.
0193 * @param start The starting angle of the arc in degrees.
0194 * @param extent The angular extent of the arc in degrees.
0195 * @param type The closure type for the arc:
0196 * {@link #OPEN}, {@link #CHORD}, or {@link #PIE}.
0197 * @since 1.2
0198 */
0199 public Float(Rectangle2D ellipseBounds, float start,
0200 float extent, int type) {
0201 super (type);
0202 this .x = (float) ellipseBounds.getX();
0203 this .y = (float) ellipseBounds.getY();
0204 this .width = (float) ellipseBounds.getWidth();
0205 this .height = (float) ellipseBounds.getHeight();
0206 this .start = start;
0207 this .extent = extent;
0208 }
0209
0210 /**
0211 * {@inheritDoc}
0212 * Note that the arc
0213 * <a href="Arc2D.html#inscribes">partially inscribes</a>
0214 * the framing rectangle of this {@code RectangularShape}.
0215 *
0216 * @since 1.2
0217 */
0218 public double getX() {
0219 return (double) x;
0220 }
0221
0222 /**
0223 * {@inheritDoc}
0224 * Note that the arc
0225 * <a href="Arc2D.html#inscribes">partially inscribes</a>
0226 * the framing rectangle of this {@code RectangularShape}.
0227 *
0228 * @since 1.2
0229 */
0230 public double getY() {
0231 return (double) y;
0232 }
0233
0234 /**
0235 * {@inheritDoc}
0236 * Note that the arc
0237 * <a href="Arc2D.html#inscribes">partially inscribes</a>
0238 * the framing rectangle of this {@code RectangularShape}.
0239 *
0240 * @since 1.2
0241 */
0242 public double getWidth() {
0243 return (double) width;
0244 }
0245
0246 /**
0247 * {@inheritDoc}
0248 * Note that the arc
0249 * <a href="Arc2D.html#inscribes">partially inscribes</a>
0250 * the framing rectangle of this {@code RectangularShape}.
0251 *
0252 * @since 1.2
0253 */
0254 public double getHeight() {
0255 return (double) height;
0256 }
0257
0258 /**
0259 * {@inheritDoc}
0260 * @since 1.2
0261 */
0262 public double getAngleStart() {
0263 return (double) start;
0264 }
0265
0266 /**
0267 * {@inheritDoc}
0268 * @since 1.2
0269 */
0270 public double getAngleExtent() {
0271 return (double) extent;
0272 }
0273
0274 /**
0275 * {@inheritDoc}
0276 * @since 1.2
0277 */
0278 public boolean isEmpty() {
0279 return (width <= 0.0 || height <= 0.0);
0280 }
0281
0282 /**
0283 * {@inheritDoc}
0284 * @since 1.2
0285 */
0286 public void setArc(double x, double y, double w, double h,
0287 double angSt, double angExt, int closure) {
0288 this .setArcType(closure);
0289 this .x = (float) x;
0290 this .y = (float) y;
0291 this .width = (float) w;
0292 this .height = (float) h;
0293 this .start = (float) angSt;
0294 this .extent = (float) angExt;
0295 }
0296
0297 /**
0298 * {@inheritDoc}
0299 * @since 1.2
0300 */
0301 public void setAngleStart(double angSt) {
0302 this .start = (float) angSt;
0303 }
0304
0305 /**
0306 * {@inheritDoc}
0307 * @since 1.2
0308 */
0309 public void setAngleExtent(double angExt) {
0310 this .extent = (float) angExt;
0311 }
0312
0313 /**
0314 * {@inheritDoc}
0315 * @since 1.2
0316 */
0317 protected Rectangle2D makeBounds(double x, double y, double w,
0318 double h) {
0319 return new Rectangle2D.Float((float) x, (float) y,
0320 (float) w, (float) h);
0321 }
0322
0323 /*
0324 * JDK 1.6 serialVersionUID
0325 */
0326 private static final long serialVersionUID = 9130893014586380278L;
0327
0328 /**
0329 * Writes the default serializable fields to the
0330 * <code>ObjectOutputStream</code> followed by a byte
0331 * indicating the arc type of this <code>Arc2D</code>
0332 * instance.
0333 *
0334 * @serialData
0335 * <ol>
0336 * <li>The default serializable fields.
0337 * <li>
0338 * followed by a <code>byte</code> indicating the arc type
0339 * {@link #OPEN}, {@link #CHORD}, or {@link #PIE}.
0340 * </ol>
0341 */
0342 private void writeObject(java.io.ObjectOutputStream s)
0343 throws java.io.IOException {
0344 s.defaultWriteObject();
0345
0346 s.writeByte(getArcType());
0347 }
0348
0349 /**
0350 * Reads the default serializable fields from the
0351 * <code>ObjectInputStream</code> followed by a byte
0352 * indicating the arc type of this <code>Arc2D</code>
0353 * instance.
0354 *
0355 * @serialData
0356 * <ol>
0357 * <li>The default serializable fields.
0358 * <li>
0359 * followed by a <code>byte</code> indicating the arc type
0360 * {@link #OPEN}, {@link #CHORD}, or {@link #PIE}.
0361 * </ol>
0362 */
0363 private void readObject(java.io.ObjectInputStream s)
0364 throws java.lang.ClassNotFoundException,
0365 java.io.IOException {
0366 s.defaultReadObject();
0367
0368 try {
0369 setArcType(s.readByte());
0370 } catch (IllegalArgumentException iae) {
0371 throw new java.io.InvalidObjectException(iae
0372 .getMessage());
0373 }
0374 }
0375 }
0376
0377 /**
0378 * This class defines an arc specified in {@code double} precision.
0379 * @since 1.2
0380 */
0381 public static class Double extends Arc2D implements Serializable {
0382 /**
0383 * The X coordinate of the upper-left corner of the framing
0384 * rectangle of the arc.
0385 * @since 1.2
0386 * @serial
0387 */
0388 public double x;
0389
0390 /**
0391 * The Y coordinate of the upper-left corner of the framing
0392 * rectangle of the arc.
0393 * @since 1.2
0394 * @serial
0395 */
0396 public double y;
0397
0398 /**
0399 * The overall width of the full ellipse of which this arc is
0400 * a partial section (not considering the angular extents).
0401 * @since 1.2
0402 * @serial
0403 */
0404 public double width;
0405
0406 /**
0407 * The overall height of the full ellipse of which this arc is
0408 * a partial section (not considering the angular extents).
0409 * @since 1.2
0410 * @serial
0411 */
0412 public double height;
0413
0414 /**
0415 * The starting angle of the arc in degrees.
0416 * @since 1.2
0417 * @serial
0418 */
0419 public double start;
0420
0421 /**
0422 * The angular extent of the arc in degrees.
0423 * @since 1.2
0424 * @serial
0425 */
0426 public double extent;
0427
0428 /**
0429 * Constructs a new OPEN arc, initialized to location (0, 0),
0430 * size (0, 0), angular extents (start = 0, extent = 0).
0431 * @since 1.2
0432 */
0433 public Double() {
0434 super (OPEN);
0435 }
0436
0437 /**
0438 * Constructs a new arc, initialized to location (0, 0),
0439 * size (0, 0), angular extents (start = 0, extent = 0), and
0440 * the specified closure type.
0441 *
0442 * @param type The closure type for the arc:
0443 * {@link #OPEN}, {@link #CHORD}, or {@link #PIE}.
0444 * @since 1.2
0445 */
0446 public Double(int type) {
0447 super (type);
0448 }
0449
0450 /**
0451 * Constructs a new arc, initialized to the specified location,
0452 * size, angular extents, and closure type.
0453 *
0454 * @param x The X coordinate of the upper-left corner
0455 * of the arc's framing rectangle.
0456 * @param y The Y coordinate of the upper-left corner
0457 * of the arc's framing rectangle.
0458 * @param w The overall width of the full ellipse of which this
0459 * arc is a partial section.
0460 * @param h The overall height of the full ellipse of which this
0461 * arc is a partial section.
0462 * @param start The starting angle of the arc in degrees.
0463 * @param extent The angular extent of the arc in degrees.
0464 * @param type The closure type for the arc:
0465 * {@link #OPEN}, {@link #CHORD}, or {@link #PIE}.
0466 * @since 1.2
0467 */
0468 public Double(double x, double y, double w, double h,
0469 double start, double extent, int type) {
0470 super (type);
0471 this .x = x;
0472 this .y = y;
0473 this .width = w;
0474 this .height = h;
0475 this .start = start;
0476 this .extent = extent;
0477 }
0478
0479 /**
0480 * Constructs a new arc, initialized to the specified location,
0481 * size, angular extents, and closure type.
0482 *
0483 * @param ellipseBounds The framing rectangle that defines the
0484 * outer boundary of the full ellipse of which this arc is a
0485 * partial section.
0486 * @param start The starting angle of the arc in degrees.
0487 * @param extent The angular extent of the arc in degrees.
0488 * @param type The closure type for the arc:
0489 * {@link #OPEN}, {@link #CHORD}, or {@link #PIE}.
0490 * @since 1.2
0491 */
0492 public Double(Rectangle2D ellipseBounds, double start,
0493 double extent, int type) {
0494 super (type);
0495 this .x = ellipseBounds.getX();
0496 this .y = ellipseBounds.getY();
0497 this .width = ellipseBounds.getWidth();
0498 this .height = ellipseBounds.getHeight();
0499 this .start = start;
0500 this .extent = extent;
0501 }
0502
0503 /**
0504 * {@inheritDoc}
0505 * Note that the arc
0506 * <a href="Arc2D.html#inscribes">partially inscribes</a>
0507 * the framing rectangle of this {@code RectangularShape}.
0508 *
0509 * @since 1.2
0510 */
0511 public double getX() {
0512 return x;
0513 }
0514
0515 /**
0516 * {@inheritDoc}
0517 * Note that the arc
0518 * <a href="Arc2D.html#inscribes">partially inscribes</a>
0519 * the framing rectangle of this {@code RectangularShape}.
0520 *
0521 * @since 1.2
0522 */
0523 public double getY() {
0524 return y;
0525 }
0526
0527 /**
0528 * {@inheritDoc}
0529 * Note that the arc
0530 * <a href="Arc2D.html#inscribes">partially inscribes</a>
0531 * the framing rectangle of this {@code RectangularShape}.
0532 *
0533 * @since 1.2
0534 */
0535 public double getWidth() {
0536 return width;
0537 }
0538
0539 /**
0540 * {@inheritDoc}
0541 * Note that the arc
0542 * <a href="Arc2D.html#inscribes">partially inscribes</a>
0543 * the framing rectangle of this {@code RectangularShape}.
0544 *
0545 * @since 1.2
0546 */
0547 public double getHeight() {
0548 return height;
0549 }
0550
0551 /**
0552 * {@inheritDoc}
0553 * @since 1.2
0554 */
0555 public double getAngleStart() {
0556 return start;
0557 }
0558
0559 /**
0560 * {@inheritDoc}
0561 * @since 1.2
0562 */
0563 public double getAngleExtent() {
0564 return extent;
0565 }
0566
0567 /**
0568 * {@inheritDoc}
0569 * @since 1.2
0570 */
0571 public boolean isEmpty() {
0572 return (width <= 0.0 || height <= 0.0);
0573 }
0574
0575 /**
0576 * {@inheritDoc}
0577 * @since 1.2
0578 */
0579 public void setArc(double x, double y, double w, double h,
0580 double angSt, double angExt, int closure) {
0581 this .setArcType(closure);
0582 this .x = x;
0583 this .y = y;
0584 this .width = w;
0585 this .height = h;
0586 this .start = angSt;
0587 this .extent = angExt;
0588 }
0589
0590 /**
0591 * {@inheritDoc}
0592 * @since 1.2
0593 */
0594 public void setAngleStart(double angSt) {
0595 this .start = angSt;
0596 }
0597
0598 /**
0599 * {@inheritDoc}
0600 * @since 1.2
0601 */
0602 public void setAngleExtent(double angExt) {
0603 this .extent = angExt;
0604 }
0605
0606 /**
0607 * {@inheritDoc}
0608 * @since 1.2
0609 */
0610 protected Rectangle2D makeBounds(double x, double y, double w,
0611 double h) {
0612 return new Rectangle2D.Double(x, y, w, h);
0613 }
0614
0615 /*
0616 * JDK 1.6 serialVersionUID
0617 */
0618 private static final long serialVersionUID = 728264085846882001L;
0619
0620 /**
0621 * Writes the default serializable fields to the
0622 * <code>ObjectOutputStream</code> followed by a byte
0623 * indicating the arc type of this <code>Arc2D</code>
0624 * instance.
0625 *
0626 * @serialData
0627 * <ol>
0628 * <li>The default serializable fields.
0629 * <li>
0630 * followed by a <code>byte</code> indicating the arc type
0631 * {@link #OPEN}, {@link #CHORD}, or {@link #PIE}.
0632 * </ol>
0633 */
0634 private void writeObject(java.io.ObjectOutputStream s)
0635 throws java.io.IOException {
0636 s.defaultWriteObject();
0637
0638 s.writeByte(getArcType());
0639 }
0640
0641 /**
0642 * Reads the default serializable fields from the
0643 * <code>ObjectInputStream</code> followed by a byte
0644 * indicating the arc type of this <code>Arc2D</code>
0645 * instance.
0646 *
0647 * @serialData
0648 * <ol>
0649 * <li>The default serializable fields.
0650 * <li>
0651 * followed by a <code>byte</code> indicating the arc type
0652 * {@link #OPEN}, {@link #CHORD}, or {@link #PIE}.
0653 * </ol>
0654 */
0655 private void readObject(java.io.ObjectInputStream s)
0656 throws java.lang.ClassNotFoundException,
0657 java.io.IOException {
0658 s.defaultReadObject();
0659
0660 try {
0661 setArcType(s.readByte());
0662 } catch (IllegalArgumentException iae) {
0663 throw new java.io.InvalidObjectException(iae
0664 .getMessage());
0665 }
0666 }
0667 }
0668
0669 private int type;
0670
0671 /**
0672 * This is an abstract class that cannot be instantiated directly.
0673 * Type-specific implementation subclasses are available for
0674 * instantiation and provide a number of formats for storing
0675 * the information necessary to satisfy the various accessor
0676 * methods below.
0677 * <p>
0678 * This constructor creates an object with a default closure
0679 * type of {@link #OPEN}. It is provided only to enable
0680 * serialization of subclasses.
0681 *
0682 * @see java.awt.geom.Arc2D.Float
0683 * @see java.awt.geom.Arc2D.Double
0684 */
0685 Arc2D() {
0686 this (OPEN);
0687 }
0688
0689 /**
0690 * This is an abstract class that cannot be instantiated directly.
0691 * Type-specific implementation subclasses are available for
0692 * instantiation and provide a number of formats for storing
0693 * the information necessary to satisfy the various accessor
0694 * methods below.
0695 *
0696 * @param type The closure type of this arc:
0697 * {@link #OPEN}, {@link #CHORD}, or {@link #PIE}.
0698 * @see java.awt.geom.Arc2D.Float
0699 * @see java.awt.geom.Arc2D.Double
0700 * @since 1.2
0701 */
0702 protected Arc2D(int type) {
0703 setArcType(type);
0704 }
0705
0706 /**
0707 * Returns the starting angle of the arc.
0708 *
0709 * @return A double value that represents the starting angle
0710 * of the arc in degrees.
0711 * @see #setAngleStart
0712 * @since 1.2
0713 */
0714 public abstract double getAngleStart();
0715
0716 /**
0717 * Returns the angular extent of the arc.
0718 *
0719 * @return A double value that represents the angular extent
0720 * of the arc in degrees.
0721 * @see #setAngleExtent
0722 * @since 1.2
0723 */
0724 public abstract double getAngleExtent();
0725
0726 /**
0727 * Returns the arc closure type of the arc: {@link #OPEN},
0728 * {@link #CHORD}, or {@link #PIE}.
0729 * @return One of the integer constant closure types defined
0730 * in this class.
0731 * @see #setArcType
0732 * @since 1.2
0733 */
0734 public int getArcType() {
0735 return type;
0736 }
0737
0738 /**
0739 * Returns the starting point of the arc. This point is the
0740 * intersection of the ray from the center defined by the
0741 * starting angle and the elliptical boundary of the arc.
0742 *
0743 * @return A <CODE>Point2D</CODE> object representing the
0744 * x,y coordinates of the starting point of the arc.
0745 * @since 1.2
0746 */
0747 public Point2D getStartPoint() {
0748 double angle = Math.toRadians(-getAngleStart());
0749 double x = getX() + (Math.cos(angle) * 0.5 + 0.5) * getWidth();
0750 double y = getY() + (Math.sin(angle) * 0.5 + 0.5) * getHeight();
0751 return new Point2D.Double(x, y);
0752 }
0753
0754 /**
0755 * Returns the ending point of the arc. This point is the
0756 * intersection of the ray from the center defined by the
0757 * starting angle plus the angular extent of the arc and the
0758 * elliptical boundary of the arc.
0759 *
0760 * @return A <CODE>Point2D</CODE> object representing the
0761 * x,y coordinates of the ending point of the arc.
0762 * @since 1.2
0763 */
0764 public Point2D getEndPoint() {
0765 double angle = Math.toRadians(-getAngleStart()
0766 - getAngleExtent());
0767 double x = getX() + (Math.cos(angle) * 0.5 + 0.5) * getWidth();
0768 double y = getY() + (Math.sin(angle) * 0.5 + 0.5) * getHeight();
0769 return new Point2D.Double(x, y);
0770 }
0771
0772 /**
0773 * Sets the location, size, angular extents, and closure type of
0774 * this arc to the specified double values.
0775 *
0776 * @param x The X coordinate of the upper-left corner of the arc.
0777 * @param y The Y coordinate of the upper-left corner of the arc.
0778 * @param w The overall width of the full ellipse of which
0779 * this arc is a partial section.
0780 * @param h The overall height of the full ellipse of which
0781 * this arc is a partial section.
0782 * @param angSt The starting angle of the arc in degrees.
0783 * @param angExt The angular extent of the arc in degrees.
0784 * @param closure The closure type for the arc:
0785 * {@link #OPEN}, {@link #CHORD}, or {@link #PIE}.
0786 * @since 1.2
0787 */
0788 public abstract void setArc(double x, double y, double w, double h,
0789 double angSt, double angExt, int closure);
0790
0791 /**
0792 * Sets the location, size, angular extents, and closure type of
0793 * this arc to the specified values.
0794 *
0795 * @param loc The <CODE>Point2D</CODE> representing the coordinates of
0796 * the upper-left corner of the arc.
0797 * @param size The <CODE>Dimension2D</CODE> representing the width
0798 * and height of the full ellipse of which this arc is
0799 * a partial section.
0800 * @param angSt The starting angle of the arc in degrees.
0801 * @param angExt The angular extent of the arc in degrees.
0802 * @param closure The closure type for the arc:
0803 * {@link #OPEN}, {@link #CHORD}, or {@link #PIE}.
0804 * @since 1.2
0805 */
0806 public void setArc(Point2D loc, Dimension2D size, double angSt,
0807 double angExt, int closure) {
0808 setArc(loc.getX(), loc.getY(), size.getWidth(), size
0809 .getHeight(), angSt, angExt, closure);
0810 }
0811
0812 /**
0813 * Sets the location, size, angular extents, and closure type of
0814 * this arc to the specified values.
0815 *
0816 * @param rect The framing rectangle that defines the
0817 * outer boundary of the full ellipse of which this arc is a
0818 * partial section.
0819 * @param angSt The starting angle of the arc in degrees.
0820 * @param angExt The angular extent of the arc in degrees.
0821 * @param closure The closure type for the arc:
0822 * {@link #OPEN}, {@link #CHORD}, or {@link #PIE}.
0823 * @since 1.2
0824 */
0825 public void setArc(Rectangle2D rect, double angSt, double angExt,
0826 int closure) {
0827 setArc(rect.getX(), rect.getY(), rect.getWidth(), rect
0828 .getHeight(), angSt, angExt, closure);
0829 }
0830
0831 /**
0832 * Sets this arc to be the same as the specified arc.
0833 *
0834 * @param a The <CODE>Arc2D</CODE> to use to set the arc's values.
0835 * @since 1.2
0836 */
0837 public void setArc(Arc2D a) {
0838 setArc(a.getX(), a.getY(), a.getWidth(), a.getHeight(), a
0839 .getAngleStart(), a.getAngleExtent(), a.type);
0840 }
0841
0842 /**
0843 * Sets the position, bounds, angular extents, and closure type of
0844 * this arc to the specified values. The arc is defined by a center
0845 * point and a radius rather than a framing rectangle for the full ellipse.
0846 *
0847 * @param x The X coordinate of the center of the arc.
0848 * @param y The Y coordinate of the center of the arc.
0849 * @param radius The radius of the arc.
0850 * @param angSt The starting angle of the arc in degrees.
0851 * @param angExt The angular extent of the arc in degrees.
0852 * @param closure The closure type for the arc:
0853 * {@link #OPEN}, {@link #CHORD}, or {@link #PIE}.
0854 * @since 1.2
0855 */
0856 public void setArcByCenter(double x, double y, double radius,
0857 double angSt, double angExt, int closure) {
0858 setArc(x - radius, y - radius, radius * 2.0, radius * 2.0,
0859 angSt, angExt, closure);
0860 }
0861
0862 /**
0863 * Sets the position, bounds, and angular extents of this arc to the
0864 * specified value. The starting angle of the arc is tangent to the
0865 * line specified by points (p1, p2), the ending angle is tangent to
0866 * the line specified by points (p2, p3), and the arc has the
0867 * specified radius.
0868 *
0869 * @param p1 The first point that defines the arc. The starting
0870 * angle of the arc is tangent to the line specified by points (p1, p2).
0871 * @param p2 The second point that defines the arc. The starting
0872 * angle of the arc is tangent to the line specified by points (p1, p2).
0873 * The ending angle of the arc is tangent to the line specified by
0874 * points (p2, p3).
0875 * @param p3 The third point that defines the arc. The ending angle
0876 * of the arc is tangent to the line specified by points (p2, p3).
0877 * @param radius The radius of the arc.
0878 * @since 1.2
0879 */
0880 public void setArcByTangent(Point2D p1, Point2D p2, Point2D p3,
0881 double radius) {
0882 double ang1 = Math.atan2(p1.getY() - p2.getY(), p1.getX()
0883 - p2.getX());
0884 double ang2 = Math.atan2(p3.getY() - p2.getY(), p3.getX()
0885 - p2.getX());
0886 double diff = ang2 - ang1;
0887 if (diff > Math.PI) {
0888 ang2 -= Math.PI * 2.0;
0889 } else if (diff < -Math.PI) {
0890 ang2 += Math.PI * 2.0;
0891 }
0892 double bisect = (ang1 + ang2) / 2.0;
0893 double theta = Math.abs(ang2 - bisect);
0894 double dist = radius / Math.sin(theta);
0895 double x = p2.getX() + dist * Math.cos(bisect);
0896 double y = p2.getY() + dist * Math.sin(bisect);
0897 // REMIND: This needs some work...
0898 if (ang1 < ang2) {
0899 ang1 -= Math.PI / 2.0;
0900 ang2 += Math.PI / 2.0;
0901 } else {
0902 ang1 += Math.PI / 2.0;
0903 ang2 -= Math.PI / 2.0;
0904 }
0905 ang1 = Math.toDegrees(-ang1);
0906 ang2 = Math.toDegrees(-ang2);
0907 diff = ang2 - ang1;
0908 if (diff < 0) {
0909 diff += 360;
0910 } else {
0911 diff -= 360;
0912 }
0913 setArcByCenter(x, y, radius, ang1, diff, type);
0914 }
0915
0916 /**
0917 * Sets the starting angle of this arc to the specified double
0918 * value.
0919 *
0920 * @param angSt The starting angle of the arc in degrees.
0921 * @see #getAngleStart
0922 * @since 1.2
0923 */
0924 public abstract void setAngleStart(double angSt);
0925
0926 /**
0927 * Sets the angular extent of this arc to the specified double
0928 * value.
0929 *
0930 * @param angExt The angular extent of the arc in degrees.
0931 * @see #getAngleExtent
0932 * @since 1.2
0933 */
0934 public abstract void setAngleExtent(double angExt);
0935
0936 /**
0937 * Sets the starting angle of this arc to the angle that the
0938 * specified point defines relative to the center of this arc.
0939 * The angular extent of the arc will remain the same.
0940 *
0941 * @param p The <CODE>Point2D</CODE> that defines the starting angle.
0942 * @see #getAngleStart
0943 * @since 1.2
0944 */
0945 public void setAngleStart(Point2D p) {
0946 // Bias the dx and dy by the height and width of the oval.
0947 double dx = getHeight() * (p.getX() - getCenterX());
0948 double dy = getWidth() * (p.getY() - getCenterY());
0949 setAngleStart(-Math.toDegrees(Math.atan2(dy, dx)));
0950 }
0951
0952 /**
0953 * Sets the starting angle and angular extent of this arc using two
0954 * sets of coordinates. The first set of coordinates is used to
0955 * determine the angle of the starting point relative to the arc's
0956 * center. The second set of coordinates is used to determine the
0957 * angle of the end point relative to the arc's center.
0958 * The arc will always be non-empty and extend counterclockwise
0959 * from the first point around to the second point.
0960 *
0961 * @param x1 The X coordinate of the arc's starting point.
0962 * @param y1 The Y coordinate of the arc's starting point.
0963 * @param x2 The X coordinate of the arc's ending point.
0964 * @param y2 The Y coordinate of the arc's ending point.
0965 * @since 1.2
0966 */
0967 public void setAngles(double x1, double y1, double x2, double y2) {
0968 double x = getCenterX();
0969 double y = getCenterY();
0970 double w = getWidth();
0971 double h = getHeight();
0972 // Note: reversing the Y equations negates the angle to adjust
0973 // for the upside down coordinate system.
0974 // Also we should bias atans by the height and width of the oval.
0975 double ang1 = Math.atan2(w * (y - y1), h * (x1 - x));
0976 double ang2 = Math.atan2(w * (y - y2), h * (x2 - x));
0977 ang2 -= ang1;
0978 if (ang2 <= 0.0) {
0979 ang2 += Math.PI * 2.0;
0980 }
0981 setAngleStart(Math.toDegrees(ang1));
0982 setAngleExtent(Math.toDegrees(ang2));
0983 }
0984
0985 /**
0986 * Sets the starting angle and angular extent of this arc using
0987 * two points. The first point is used to determine the angle of
0988 * the starting point relative to the arc's center.
0989 * The second point is used to determine the angle of the end point
0990 * relative to the arc's center.
0991 * The arc will always be non-empty and extend counterclockwise
0992 * from the first point around to the second point.
0993 *
0994 * @param p1 The <CODE>Point2D</CODE> that defines the arc's
0995 * starting point.
0996 * @param p2 The <CODE>Point2D</CODE> that defines the arc's
0997 * ending point.
0998 * @since 1.2
0999 */
1000 public void setAngles(Point2D p1, Point2D p2) {
1001 setAngles(p1.getX(), p1.getY(), p2.getX(), p2.getY());
1002 }
1003
1004 /**
1005 * Sets the closure type of this arc to the specified value:
1006 * <CODE>OPEN</CODE>, <CODE>CHORD</CODE>, or <CODE>PIE</CODE>.
1007 *
1008 * @param type The integer constant that represents the closure
1009 * type of this arc: {@link #OPEN}, {@link #CHORD}, or
1010 * {@link #PIE}.
1011 *
1012 * @throws IllegalArgumentException if <code>type</code> is not
1013 * 0, 1, or 2.+
1014 * @see #getArcType
1015 * @since 1.2
1016 */
1017 public void setArcType(int type) {
1018 if (type < OPEN || type > PIE) {
1019 throw new IllegalArgumentException("invalid type for Arc: "
1020 + type);
1021 }
1022 this .type = type;
1023 }
1024
1025 /**
1026 * {@inheritDoc}
1027 * Note that the arc
1028 * <a href="Arc2D.html#inscribes">partially inscribes</a>
1029 * the framing rectangle of this {@code RectangularShape}.
1030 *
1031 * @since 1.2
1032 */
1033 public void setFrame(double x, double y, double w, double h) {
1034 setArc(x, y, w, h, getAngleStart(), getAngleExtent(), type);
1035 }
1036
1037 /**
1038 * Returns the high-precision framing rectangle of the arc. The framing
1039 * rectangle contains only the part of this <code>Arc2D</code> that is
1040 * in between the starting and ending angles and contains the pie
1041 * wedge, if this <code>Arc2D</code> has a <code>PIE</code> closure type.
1042 * <p>
1043 * This method differs from the
1044 * {@link RectangularShape#getBounds() getBounds} in that the
1045 * <code>getBounds</code> method only returns the bounds of the
1046 * enclosing ellipse of this <code>Arc2D</code> without considering
1047 * the starting and ending angles of this <code>Arc2D</code>.
1048 *
1049 * @return the <CODE>Rectangle2D</CODE> that represents the arc's
1050 * framing rectangle.
1051 * @since 1.2
1052 */
1053 public Rectangle2D getBounds2D() {
1054 if (isEmpty()) {
1055 return makeBounds(getX(), getY(), getWidth(), getHeight());
1056 }
1057 double x1, y1, x2, y2;
1058 if (getArcType() == PIE) {
1059 x1 = y1 = x2 = y2 = 0.0;
1060 } else {
1061 x1 = y1 = 1.0;
1062 x2 = y2 = -1.0;
1063 }
1064 double angle = 0.0;
1065 for (int i = 0; i < 6; i++) {
1066 if (i < 4) {
1067 // 0-3 are the four quadrants
1068 angle += 90.0;
1069 if (!containsAngle(angle)) {
1070 continue;
1071 }
1072 } else if (i == 4) {
1073 // 4 is start angle
1074 angle = getAngleStart();
1075 } else {
1076 // 5 is end angle
1077 angle += getAngleExtent();
1078 }
1079 double rads = Math.toRadians(-angle);
1080 double xe = Math.cos(rads);
1081 double ye = Math.sin(rads);
1082 x1 = Math.min(x1, xe);
1083 y1 = Math.min(y1, ye);
1084 x2 = Math.max(x2, xe);
1085 y2 = Math.max(y2, ye);
1086 }
1087 double w = getWidth();
1088 double h = getHeight();
1089 x2 = (x2 - x1) * 0.5 * w;
1090 y2 = (y2 - y1) * 0.5 * h;
1091 x1 = getX() + (x1 * 0.5 + 0.5) * w;
1092 y1 = getY() + (y1 * 0.5 + 0.5) * h;
1093 return makeBounds(x1, y1, x2, y2);
1094 }
1095
1096 /**
1097 * Constructs a <code>Rectangle2D</code> of the appropriate precision
1098 * to hold the parameters calculated to be the framing rectangle
1099 * of this arc.
1100 *
1101 * @param x The X coordinate of the upper-left corner of the
1102 * framing rectangle.
1103 * @param y The Y coordinate of the upper-left corner of the
1104 * framing rectangle.
1105 * @param w The width of the framing rectangle.
1106 * @param h The height of the framing rectangle.
1107 * @return a <code>Rectangle2D</code> that is the framing rectangle
1108 * of this arc.
1109 * @since 1.2
1110 */
1111 protected abstract Rectangle2D makeBounds(double x, double y,
1112 double w, double h);
1113
1114 /*
1115 * Normalizes the specified angle into the range -180 to 180.
1116 */
1117 static double normalizeDegrees(double angle) {
1118 if (angle > 180.0) {
1119 if (angle <= (180.0 + 360.0)) {
1120 angle = angle - 360.0;
1121 } else {
1122 angle = Math.IEEEremainder(angle, 360.0);
1123 // IEEEremainder can return -180 here for some input values...
1124 if (angle == -180.0) {
1125 angle = 180.0;
1126 }
1127 }
1128 } else if (angle <= -180.0) {
1129 if (angle > (-180.0 - 360.0)) {
1130 angle = angle + 360.0;
1131 } else {
1132 angle = Math.IEEEremainder(angle, 360.0);
1133 // IEEEremainder can return -180 here for some input values...
1134 if (angle == -180.0) {
1135 angle = 180.0;
1136 }
1137 }
1138 }
1139 return angle;
1140 }
1141
1142 /**
1143 * Determines whether or not the specified angle is within the
1144 * angular extents of the arc.
1145 *
1146 * @param angle The angle to test.
1147 *
1148 * @return <CODE>true</CODE> if the arc contains the angle,
1149 * <CODE>false</CODE> if the arc doesn't contain the angle.
1150 * @since 1.2
1151 */
1152 public boolean containsAngle(double angle) {
1153 double angExt = getAngleExtent();
1154 boolean backwards = (angExt < 0.0);
1155 if (backwards) {
1156 angExt = -angExt;
1157 }
1158 if (angExt >= 360.0) {
1159 return true;
1160 }
1161 angle = normalizeDegrees(angle)
1162 - normalizeDegrees(getAngleStart());
1163 if (backwards) {
1164 angle = -angle;
1165 }
1166 if (angle < 0.0) {
1167 angle += 360.0;
1168 }
1169
1170 return (angle >= 0.0) && (angle < angExt);
1171 }
1172
1173 /**
1174 * Determines whether or not the specified point is inside the boundary
1175 * of the arc.
1176 *
1177 * @param x The X coordinate of the point to test.
1178 * @param y The Y coordinate of the point to test.
1179 *
1180 * @return <CODE>true</CODE> if the point lies within the bound of
1181 * the arc, <CODE>false</CODE> if the point lies outside of the
1182 * arc's bounds.
1183 * @since 1.2
1184 */
1185 public boolean contains(double x, double y) {
1186 // Normalize the coordinates compared to the ellipse
1187 // having a center at 0,0 and a radius of 0.5.
1188 double ellw = getWidth();
1189 if (ellw <= 0.0) {
1190 return false;
1191 }
1192 double normx = (x - getX()) / ellw - 0.5;
1193 double ellh = getHeight();
1194 if (ellh <= 0.0) {
1195 return false;
1196 }
1197 double normy = (y - getY()) / ellh - 0.5;
1198 double distSq = (normx * normx + normy * normy);
1199 if (distSq >= 0.25) {
1200 return false;
1201 }
1202 double angExt = Math.abs(getAngleExtent());
1203 if (angExt >= 360.0) {
1204 return true;
1205 }
1206 boolean inarc = containsAngle(-Math.toDegrees(Math.atan2(normy,
1207 normx)));
1208 if (type == PIE) {
1209 return inarc;
1210 }
1211 // CHORD and OPEN behave the same way
1212 if (inarc) {
1213 if (angExt >= 180.0) {
1214 return true;
1215 }
1216 // point must be outside the "pie triangle"
1217 } else {
1218 if (angExt <= 180.0) {
1219 return false;
1220 }
1221 // point must be inside the "pie triangle"
1222 }
1223 // The point is inside the pie triangle iff it is on the same
1224 // side of the line connecting the ends of the arc as the center.
1225 double angle = Math.toRadians(-getAngleStart());
1226 double x1 = Math.cos(angle);
1227 double y1 = Math.sin(angle);
1228 angle += Math.toRadians(-getAngleExtent());
1229 double x2 = Math.cos(angle);
1230 double y2 = Math.sin(angle);
1231 boolean inside = (Line2D.relativeCCW(x1, y1, x2, y2, 2 * normx,
1232 2 * normy)
1233 * Line2D.relativeCCW(x1, y1, x2, y2, 0, 0) >= 0);
1234 return inarc ? !inside : inside;
1235 }
1236
1237 /**
1238 * Determines whether or not the interior of the arc intersects
1239 * the interior of the specified rectangle.
1240 *
1241 * @param x The X coordinate of the rectangle's upper-left corner.
1242 * @param y The Y coordinate of the rectangle's upper-left corner.
1243 * @param w The width of the rectangle.
1244 * @param h The height of the rectangle.
1245 *
1246 * @return <CODE>true</CODE> if the arc intersects the rectangle,
1247 * <CODE>false</CODE> if the arc doesn't intersect the rectangle.
1248 * @since 1.2
1249 */
1250 public boolean intersects(double x, double y, double w, double h) {
1251
1252 double aw = getWidth();
1253 double ah = getHeight();
1254
1255 if (w <= 0 || h <= 0 || aw <= 0 || ah <= 0) {
1256 return false;
1257 }
1258 double ext = getAngleExtent();
1259 if (ext == 0) {
1260 return false;
1261 }
1262
1263 double ax = getX();
1264 double ay = getY();
1265 double axw = ax + aw;
1266 double ayh = ay + ah;
1267 double xw = x + w;
1268 double yh = y + h;
1269
1270 // check bbox
1271 if (x >= axw || y >= ayh || xw <= ax || yh <= ay) {
1272 return false;
1273 }
1274
1275 // extract necessary data
1276 double axc = getCenterX();
1277 double ayc = getCenterY();
1278 Point2D sp = getStartPoint();
1279 Point2D ep = getEndPoint();
1280 double sx = sp.getX();
1281 double sy = sp.getY();
1282 double ex = ep.getX();
1283 double ey = ep.getY();
1284
1285 /*
1286 * Try to catch rectangles that intersect arc in areas
1287 * outside of rectagle with left top corner coordinates
1288 * (min(center x, start point x, end point x),
1289 * min(center y, start point y, end point y))
1290 * and rigth bottom corner coordinates
1291 * (max(center x, start point x, end point x),
1292 * max(center y, start point y, end point y)).
1293 * So we'll check axis segments outside of rectangle above.
1294 */
1295 if (ayc >= y && ayc <= yh) { // 0 and 180
1296 if ((sx < xw && ex < xw && axc < xw && axw > x && containsAngle(0))
1297 || (sx > x && ex > x && axc > x && ax < xw && containsAngle(180))) {
1298 return true;
1299 }
1300 }
1301 if (axc >= x && axc <= xw) { // 90 and 270
1302 if ((sy > y && ey > y && ayc > y && ay < yh && containsAngle(90))
1303 || (sy < yh && ey < yh && ayc < yh && ayh > y && containsAngle(270))) {
1304 return true;
1305 }
1306 }
1307
1308 /*
1309 * For PIE we should check intersection with pie slices;
1310 * also we should do the same for arcs with extent is greater
1311 * than 180, because we should cover case of rectangle, which
1312 * situated between center of arc and chord, but does not
1313 * intersect the chord.
1314 */
1315 Rectangle2D rect = new Rectangle2D.Double(x, y, w, h);
1316 if (type == PIE || Math.abs(ext) > 180) {
1317 // for PIE: try to find intersections with pie slices
1318 if (rect.intersectsLine(axc, ayc, sx, sy)
1319 || rect.intersectsLine(axc, ayc, ex, ey)) {
1320 return true;
1321 }
1322 } else {
1323 // for CHORD and OPEN: try to find intersections with chord
1324 if (rect.intersectsLine(sx, sy, ex, ey)) {
1325 return true;
1326 }
1327 }
1328
1329 // finally check the rectangle corners inside the arc
1330 if (contains(x, y) || contains(x + w, y) || contains(x, y + h)
1331 || contains(x + w, y + h)) {
1332 return true;
1333 }
1334
1335 return false;
1336 }
1337
1338 /**
1339 * Determines whether or not the interior of the arc entirely contains
1340 * the specified rectangle.
1341 *
1342 * @param x The X coordinate of the rectangle's upper-left corner.
1343 * @param y The Y coordinate of the rectangle's upper-left corner.
1344 * @param w The width of the rectangle.
1345 * @param h The height of the rectangle.
1346 *
1347 * @return <CODE>true</CODE> if the arc contains the rectangle,
1348 * <CODE>false</CODE> if the arc doesn't contain the rectangle.
1349 * @since 1.2
1350 */
1351 public boolean contains(double x, double y, double w, double h) {
1352 return contains(x, y, w, h, null);
1353 }
1354
1355 /**
1356 * Determines whether or not the interior of the arc entirely contains
1357 * the specified rectangle.
1358 *
1359 * @param r The <CODE>Rectangle2D</CODE> to test.
1360 *
1361 * @return <CODE>true</CODE> if the arc contains the rectangle,
1362 * <CODE>false</CODE> if the arc doesn't contain the rectangle.
1363 * @since 1.2
1364 */
1365 public boolean contains(Rectangle2D r) {
1366 return contains(r.getX(), r.getY(), r.getWidth(),
1367 r.getHeight(), r);
1368 }
1369
1370 private boolean contains(double x, double y, double w, double h,
1371 Rectangle2D origrect) {
1372 if (!(contains(x, y) && contains(x + w, y)
1373 && contains(x, y + h) && contains(x + w, y + h))) {
1374 return false;
1375 }
1376 // If the shape is convex then we have done all the testing
1377 // we need. Only PIE arcs can be concave and then only if
1378 // the angular extents are greater than 180 degrees.
1379 if (type != PIE || Math.abs(getAngleExtent()) <= 180.0) {
1380 return true;
1381 }
1382 // For a PIE shape we have an additional test for the case where
1383 // the angular extents are greater than 180 degrees and all four
1384 // rectangular corners are inside the shape but one of the
1385 // rectangle edges spans across the "missing wedge" of the arc.
1386 // We can test for this case by checking if the rectangle intersects
1387 // either of the pie angle segments.
1388 if (origrect == null) {
1389 origrect = new Rectangle2D.Double(x, y, w, h);
1390 }
1391 double halfW = getWidth() / 2.0;
1392 double halfH = getHeight() / 2.0;
1393 double xc = getX() + halfW;
1394 double yc = getY() + halfH;
1395 double angle = Math.toRadians(-getAngleStart());
1396 double xe = xc + halfW * Math.cos(angle);
1397 double ye = yc + halfH * Math.sin(angle);
1398 if (origrect.intersectsLine(xc, yc, xe, ye)) {
1399 return false;
1400 }
1401 angle += Math.toRadians(-getAngleExtent());
1402 xe = xc + halfW * Math.cos(angle);
1403 ye = yc + halfH * Math.sin(angle);
1404 return !origrect.intersectsLine(xc, yc, xe, ye);
1405 }
1406
1407 /**
1408 * Returns an iteration object that defines the boundary of the
1409 * arc.
1410 * This iterator is multithread safe.
1411 * <code>Arc2D</code> guarantees that
1412 * modifications to the geometry of the arc
1413 * do not affect any iterations of that geometry that
1414 * are already in process.
1415 *
1416 * @param at an optional <CODE>AffineTransform</CODE> to be applied
1417 * to the coordinates as they are returned in the iteration, or null
1418 * if the untransformed coordinates are desired.
1419 *
1420 * @return A <CODE>PathIterator</CODE> that defines the arc's boundary.
1421 * @since 1.2
1422 */
1423 public PathIterator getPathIterator(AffineTransform at) {
1424 return new ArcIterator(this , at);
1425 }
1426
1427 /**
1428 * Returns the hashcode for this <code>Arc2D</code>.
1429 * @return the hashcode for this <code>Arc2D</code>.
1430 * @since 1.6
1431 */
1432 public int hashCode() {
1433 long bits = java.lang.Double.doubleToLongBits(getX());
1434 bits += java.lang.Double.doubleToLongBits(getY()) * 37;
1435 bits += java.lang.Double.doubleToLongBits(getWidth()) * 43;
1436 bits += java.lang.Double.doubleToLongBits(getHeight()) * 47;
1437 bits += java.lang.Double.doubleToLongBits(getAngleStart()) * 53;
1438 bits += java.lang.Double.doubleToLongBits(getAngleExtent()) * 59;
1439 bits += getArcType() * 61;
1440 return (((int) bits) ^ ((int) (bits >> 32)));
1441 }
1442
1443 /**
1444 * Determines whether or not the specified <code>Object</code> is
1445 * equal to this <code>Arc2D</code>. The specified
1446 * <code>Object</code> is equal to this <code>Arc2D</code>
1447 * if it is an instance of <code>Arc2D</code> and if its
1448 * location, size, arc extents and type are the same as this
1449 * <code>Arc2D</code>.
1450 * @param obj an <code>Object</code> to be compared with this
1451 * <code>Arc2D</code>.
1452 * @return <code>true</code> if <code>obj</code> is an instance
1453 * of <code>Arc2D</code> and has the same values;
1454 * <code>false</code> otherwise.
1455 * @since 1.6
1456 */
1457 public boolean equals(Object obj) {
1458 if (obj == this ) {
1459 return true;
1460 }
1461 if (obj instanceof Arc2D) {
1462 Arc2D a2d = (Arc2D) obj;
1463 return ((getX() == a2d.getX()) && (getY() == a2d.getY())
1464 && (getWidth() == a2d.getWidth())
1465 && (getHeight() == a2d.getHeight())
1466 && (getAngleStart() == a2d.getAngleStart())
1467 && (getAngleExtent() == a2d.getAngleExtent()) && (getArcType() == a2d
1468 .getArcType()));
1469 }
1470 return false;
1471 }
1472 }
|