mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			1414 lines
		
	
	
		
			39 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			1414 lines
		
	
	
		
			39 KiB
		
	
	
	
		
			Java
		
	
	
	
| /* Arc2D.java -- represents an arc in 2-D space
 | |
|    Copyright (C) 2002, 2003, 2004 Free Software Foundation
 | |
| 
 | |
| This file is part of GNU Classpath.
 | |
| 
 | |
| GNU Classpath is free software; you can redistribute it and/or modify
 | |
| it under the terms of the GNU General Public License as published by
 | |
| the Free Software Foundation; either version 2, or (at your option)
 | |
| any later version.
 | |
| 
 | |
| GNU Classpath is distributed in the hope that it will be useful, but
 | |
| WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | |
| General Public License for more details.
 | |
| 
 | |
| You should have received a copy of the GNU General Public License
 | |
| along with GNU Classpath; see the file COPYING.  If not, write to the
 | |
| Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | |
| 02110-1301 USA.
 | |
| 
 | |
| Linking this library statically or dynamically with other modules is
 | |
| making a combined work based on this library.  Thus, the terms and
 | |
| conditions of the GNU General Public License cover the whole
 | |
| combination.
 | |
| 
 | |
| As a special exception, the copyright holders of this library give you
 | |
| permission to link this library with independent modules to produce an
 | |
| executable, regardless of the license terms of these independent
 | |
| modules, and to copy and distribute the resulting executable under
 | |
| terms of your choice, provided that you also meet, for each linked
 | |
| independent module, the terms and conditions of the license of that
 | |
| module.  An independent module is a module which is not derived from
 | |
| or based on this library.  If you modify this library, you may extend
 | |
| this exception to your version of the library, but you are not
 | |
| obligated to do so.  If you do not wish to do so, delete this
 | |
| exception statement from your version. */
 | |
| 
 | |
| package java.awt.geom;
 | |
| 
 | |
| import java.util.NoSuchElementException;
 | |
| 
 | |
| 
 | |
| /**
 | |
|  * This class represents all arcs (segments of an ellipse in 2-D space). The
 | |
|  * arcs are defined by starting angle and extent (arc length) in degrees, as
 | |
|  * opposed to radians (like the rest of Java), and can be open, chorded, or
 | |
|  * wedge shaped. The angles are skewed according to the ellipse, so that 45
 | |
|  * degrees always points to the upper right corner (positive x, negative y)
 | |
|  * of the bounding rectangle. A positive extent draws a counterclockwise arc,
 | |
|  * and while the angle can be any value, the path iterator only traverses the
 | |
|  * first 360 degrees. Storage is up to the subclasses.
 | |
|  *
 | |
|  * @author Eric Blake (ebb9@email.byu.edu)
 | |
|  * @author Sven de Marothy (sven@physto.se)
 | |
|  * @since 1.2
 | |
|  */
 | |
| public abstract class Arc2D extends RectangularShape
 | |
| {
 | |
|   /**
 | |
|    * An open arc, with no segment connecting the endpoints. This type of
 | |
|    * arc still contains the same points as a chorded version.
 | |
|    */
 | |
|   public static final int OPEN = 0;
 | |
| 
 | |
|   /**
 | |
|    * A closed arc with a single segment connecting the endpoints (a chord).
 | |
|    */
 | |
|   public static final int CHORD = 1;
 | |
| 
 | |
|   /**
 | |
|    * A closed arc with two segments, one from each endpoint, meeting at the
 | |
|    * center of the ellipse.
 | |
|    */
 | |
|   public static final int PIE = 2;
 | |
| 
 | |
|   /** The closure type of this arc.  This is package-private to avoid an
 | |
|    * accessor method.  */
 | |
|   int type;
 | |
| 
 | |
|   /**
 | |
|    * Create a new arc, with the specified closure type.
 | |
|    *
 | |
|    * @param type one of {@link #OPEN}, {@link #CHORD}, or {@link #PIE}.
 | |
|    * @throws IllegalArgumentException if type is invalid
 | |
|    */
 | |
|   protected Arc2D(int type)
 | |
|   {
 | |
|     if (type < OPEN || type > PIE)
 | |
|       throw new IllegalArgumentException();
 | |
|     this.type = type;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Get the starting angle of the arc in degrees.
 | |
|    *
 | |
|    * @return the starting angle
 | |
|    * @see #setAngleStart(double)
 | |
|    */
 | |
|   public abstract double getAngleStart();
 | |
| 
 | |
|   /**
 | |
|    * Get the extent angle of the arc in degrees.
 | |
|    *
 | |
|    * @return the extent angle
 | |
|    * @see #setAngleExtent(double)
 | |
|    */
 | |
|   public abstract double getAngleExtent();
 | |
| 
 | |
|   /**
 | |
|    * Return the closure type of the arc.
 | |
|    *
 | |
|    * @return the closure type
 | |
|    * @see #OPEN
 | |
|    * @see #CHORD
 | |
|    * @see #PIE
 | |
|    * @see #setArcType(int)
 | |
|    */
 | |
|   public int getArcType()
 | |
|   {
 | |
|     return type;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the starting point of the arc.
 | |
|    *
 | |
|    * @return the start point
 | |
|    */
 | |
|   public Point2D getStartPoint()
 | |
|   {
 | |
|     double angle = Math.toRadians(getAngleStart());
 | |
|     double rx = getWidth() / 2;
 | |
|     double ry = getHeight() / 2;
 | |
|     double x = getX() + rx + rx * Math.cos(angle);
 | |
|     double y = getY() + ry - ry * Math.sin(angle);
 | |
|     return new Point2D.Double(x, y);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the ending point of the arc.
 | |
|    *
 | |
|    * @return the end point
 | |
|    */
 | |
|   public Point2D getEndPoint()
 | |
|   {
 | |
|     double angle = Math.toRadians(getAngleStart() + getAngleExtent());
 | |
|     double rx = getWidth() / 2;
 | |
|     double ry = getHeight() / 2;
 | |
|     double x = getX() + rx + rx * Math.cos(angle);
 | |
|     double y = getY() + ry - ry * Math.sin(angle);
 | |
|     return new Point2D.Double(x, y);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Set the parameters of the arc. The angles are in degrees, and a positive
 | |
|    * extent sweeps counterclockwise (from the positive x-axis to the negative
 | |
|    * y-axis).
 | |
|    *
 | |
|    * @param x the new x coordinate of the upper left of the bounding box
 | |
|    * @param y the new y coordinate of the upper left of the bounding box
 | |
|    * @param w the new width of the bounding box
 | |
|    * @param h the new height of the bounding box
 | |
|    * @param start the start angle, in degrees
 | |
|    * @param extent the arc extent, in degrees
 | |
|    * @param type one of {@link #OPEN}, {@link #CHORD}, or {@link #PIE}
 | |
|    * @throws IllegalArgumentException if type is invalid
 | |
|    */
 | |
|   public abstract void setArc(double x, double y, double w, double h,
 | |
|                               double start, double extent, int type);
 | |
| 
 | |
|   /**
 | |
|    * Set the parameters of the arc. The angles are in degrees, and a positive
 | |
|    * extent sweeps counterclockwise (from the positive x-axis to the negative
 | |
|    * y-axis).
 | |
|    *
 | |
|    * @param p the upper left point of the bounding box
 | |
|    * @param d the dimensions of the bounding box
 | |
|    * @param start the start angle, in degrees
 | |
|    * @param extent the arc extent, in degrees
 | |
|    * @param type one of {@link #OPEN}, {@link #CHORD}, or {@link #PIE}
 | |
|    * @throws IllegalArgumentException if type is invalid
 | |
|    * @throws NullPointerException if p or d is null
 | |
|    */
 | |
|   public void setArc(Point2D p, Dimension2D d, double start, double extent,
 | |
|                      int type)
 | |
|   {
 | |
|     setArc(p.getX(), p.getY(), d.getWidth(), d.getHeight(), start, extent, type);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Set the parameters of the arc. The angles are in degrees, and a positive
 | |
|    * extent sweeps counterclockwise (from the positive x-axis to the negative
 | |
|    * y-axis).
 | |
|    *
 | |
|    * @param r the new bounding box
 | |
|    * @param start the start angle, in degrees
 | |
|    * @param extent the arc extent, in degrees
 | |
|    * @param type one of {@link #OPEN}, {@link #CHORD}, or {@link #PIE}
 | |
|    * @throws IllegalArgumentException if type is invalid
 | |
|    * @throws NullPointerException if r is null
 | |
|    */
 | |
|   public void setArc(Rectangle2D r, double start, double extent, int type)
 | |
|   {
 | |
|     setArc(r.getX(), r.getY(), r.getWidth(), r.getHeight(), start, extent, type);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Set the parameters of the arc from the given one.
 | |
|    *
 | |
|    * @param a the arc to copy
 | |
|    * @throws NullPointerException if a is null
 | |
|    */
 | |
|   public void setArc(Arc2D a)
 | |
|   {
 | |
|     setArc(a.getX(), a.getY(), a.getWidth(), a.getHeight(), a.getAngleStart(),
 | |
|            a.getAngleExtent(), a.getArcType());
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Set the parameters of the arc. The angles are in degrees, and a positive
 | |
|    * extent sweeps counterclockwise (from the positive x-axis to the negative
 | |
|    * y-axis). This controls the center point and radius, so the arc will be
 | |
|    * circular.
 | |
|    *
 | |
|    * @param x the x coordinate of the center of the circle
 | |
|    * @param y the y coordinate of the center of the circle
 | |
|    * @param r the radius of the circle
 | |
|    * @param start the start angle, in degrees
 | |
|    * @param extent the arc extent, in degrees
 | |
|    * @param type one of {@link #OPEN}, {@link #CHORD}, or {@link #PIE}
 | |
|    * @throws IllegalArgumentException if type is invalid
 | |
|    */
 | |
|   public void setArcByCenter(double x, double y, double r, double start,
 | |
|                              double extent, int type)
 | |
|   {
 | |
|     setArc(x - r, y - r, r + r, r + r, start, extent, type);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Sets the parameters of the arc by finding the tangents of two lines, and
 | |
|    * using the specified radius. The arc will be circular, will begin on the
 | |
|    * tangent point of the line extending from p1 to p2, and will end on the
 | |
|    * tangent point of the line extending from p2 to p3.
 | |
|    *
 | |
|    * XXX What happens if the points are colinear, or the radius negative?
 | |
|    *
 | |
|    * @param p1 the first point
 | |
|    * @param p2 the tangent line intersection point
 | |
|    * @param p3 the third point
 | |
|    * @param r the radius of the arc
 | |
|    * @throws NullPointerException if any point is null
 | |
|    */
 | |
|   public void setArcByTangent(Point2D p1, Point2D p2, Point2D p3, double r)
 | |
|   {
 | |
|     if ((p2.getX() - p1.getX()) * (p3.getY() - p1.getY())
 | |
|         - (p3.getX() - p1.getX()) * (p2.getY() - p1.getY()) > 0)
 | |
|       {
 | |
|         Point2D p = p3;
 | |
|         p3 = p1;
 | |
|         p1 = p;
 | |
|       }
 | |
| 
 | |
|     // normalized tangent vectors
 | |
|     double dx1 = (p1.getX() - p2.getX()) / p1.distance(p2);
 | |
|     double dy1 = (p1.getY() - p2.getY()) / p1.distance(p2);
 | |
|     double dx2 = (p2.getX() - p3.getX()) / p3.distance(p2);
 | |
|     double dy2 = (p2.getY() - p3.getY()) / p3.distance(p2);
 | |
|     double theta1 = Math.atan2(dx1, dy1);
 | |
|     double theta2 = Math.atan2(dx2, dy2);
 | |
| 
 | |
|     double dx = r * Math.cos(theta2) - r * Math.cos(theta1);
 | |
|     double dy = -r * Math.sin(theta2) + r * Math.sin(theta1);
 | |
| 
 | |
|     if (theta1 < 0)
 | |
|       theta1 += 2 * Math.PI;
 | |
|     if (theta2 < 0)
 | |
|       theta2 += 2 * Math.PI;
 | |
|     if (theta2 < theta1)
 | |
|       theta2 += 2 * Math.PI;
 | |
| 
 | |
|     // Vectors of the lines, not normalized, note we change
 | |
|     // the direction of line 2.
 | |
|     dx1 = p1.getX() - p2.getX();
 | |
|     dy1 = p1.getY() - p2.getY();
 | |
|     dx2 = p3.getX() - p2.getX();
 | |
|     dy2 = p3.getY() - p2.getY();
 | |
| 
 | |
|     // Calculate the tangent point to the second line
 | |
|     double t2 = -(dx1 * dy - dy1 * dx) / (dx2 * dy1 - dx1 * dy2);
 | |
|     double x2 = t2 * (p3.getX() - p2.getX()) + p2.getX();
 | |
|     double y2 = t2 * (p3.getY() - p2.getY()) + p2.getY();
 | |
| 
 | |
|     // calculate the center point
 | |
|     double x = x2 - r * Math.cos(theta2);
 | |
|     double y = y2 + r * Math.sin(theta2);
 | |
| 
 | |
|     setArc(x - r, y - r, 2 * r, 2 * r, Math.toDegrees(theta1),
 | |
|            Math.toDegrees(theta2 - theta1), getArcType());
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Set the start, in degrees.
 | |
|    *
 | |
|    * @param start the new start angle
 | |
|    * @see #getAngleStart()
 | |
|    */
 | |
|   public abstract void setAngleStart(double start);
 | |
| 
 | |
|   /**
 | |
|    * Set the extent, in degrees.
 | |
|    *
 | |
|    * @param extent the new extent angle
 | |
|    * @see #getAngleExtent()
 | |
|    */
 | |
|   public abstract void setAngleExtent(double extent);
 | |
| 
 | |
|   /**
 | |
|    * Sets the starting angle to the angle of the given point relative to
 | |
|    * the center of the arc. The extent remains constant; in other words,
 | |
|    * this rotates the arc.
 | |
|    *
 | |
|    * @param p the new start point
 | |
|    * @throws NullPointerException if p is null
 | |
|    * @see #getStartPoint()
 | |
|    * @see #getAngleStart()
 | |
|    */
 | |
|   public void setAngleStart(Point2D p)
 | |
|   {
 | |
|     // Normalize.
 | |
|     double x = p.getX() - (getX() + getWidth() / 2);
 | |
|     double y = p.getY() - (getY() + getHeight() / 2);
 | |
|     setAngleStart(Math.toDegrees(Math.atan2(-y, x)));
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Sets the starting and extent angles to those of the given points
 | |
|    * relative to the center of the arc. The arc will be non-empty, and will
 | |
|    * extend counterclockwise.
 | |
|    *
 | |
|    * @param x1 the first x coordinate
 | |
|    * @param y1 the first y coordinate
 | |
|    * @param x2 the second x coordinate
 | |
|    * @param y2 the second y coordinate
 | |
|    * @see #setAngleStart(Point2D)
 | |
|    */
 | |
|   public void setAngles(double x1, double y1, double x2, double y2)
 | |
|   {
 | |
|     // Normalize the points.
 | |
|     double mx = getX();
 | |
|     double my = getY();
 | |
|     double mw = getWidth();
 | |
|     double mh = getHeight();
 | |
|     x1 = x1 - (mx + mw / 2);
 | |
|     y1 = y1 - (my + mh / 2);
 | |
|     x2 = x2 - (mx + mw / 2);
 | |
|     y2 = y2 - (my + mh / 2);
 | |
|     double start = Math.toDegrees(Math.atan2(-y1, x1));
 | |
|     double extent = Math.toDegrees(Math.atan2(-y2, x2)) - start;
 | |
|     if (extent < 0)
 | |
|       extent += 360;
 | |
|     setAngleStart(start);
 | |
|     setAngleExtent(extent);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Sets the starting and extent angles to those of the given points
 | |
|    * relative to the center of the arc. The arc will be non-empty, and will
 | |
|    * extend counterclockwise.
 | |
|    *
 | |
|    * @param p1 the first point
 | |
|    * @param p2 the second point
 | |
|    * @throws NullPointerException if either point is null
 | |
|    * @see #setAngleStart(Point2D)
 | |
|    */
 | |
|   public void setAngles(Point2D p1, Point2D p2)
 | |
|   {
 | |
|     setAngles(p1.getX(), p1.getY(), p2.getX(), p2.getY());
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Set the closure type of this arc.
 | |
|    *
 | |
|    * @param type one of {@link #OPEN}, {@link #CHORD}, or {@link #PIE}
 | |
|    * @throws IllegalArgumentException if type is invalid
 | |
|    * @see #getArcType()
 | |
|    */
 | |
|   public void setArcType(int type)
 | |
|   {
 | |
|     if (type < OPEN || type > PIE)
 | |
|       throw new IllegalArgumentException();
 | |
|     this.type = type;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Sets the location and bounds of the ellipse of which this arc is a part.
 | |
|    *
 | |
|    * @param x the new x coordinate
 | |
|    * @param y the new y coordinate
 | |
|    * @param w the new width
 | |
|    * @param h the new height
 | |
|    * @see #getFrame()
 | |
|    */
 | |
|   public void setFrame(double x, double y, double w, double h)
 | |
|   {
 | |
|     setArc(x, y, w, h, getAngleStart(), getAngleExtent(), type);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Gets the bounds of the arc. This is much tighter than
 | |
|    * <code>getBounds</code>, as it takes into consideration the start and
 | |
|    * end angles, and the center point of a pie wedge, rather than just the
 | |
|    * overall ellipse.
 | |
|    *
 | |
|    * @return the bounds of the arc
 | |
|    * @see #getBounds()
 | |
|    */
 | |
|   public Rectangle2D getBounds2D()
 | |
|   {
 | |
|     double extent = getAngleExtent();
 | |
|     if (Math.abs(extent) >= 360)
 | |
|       return makeBounds(getX(), getY(), getWidth(), getHeight());
 | |
| 
 | |
|     // Find the minimal bounding box.  This determined by its extrema,
 | |
|     // which are the center, the endpoints of the arc, and any local
 | |
|     // maximum contained by the arc.
 | |
|     double rX = getWidth() / 2;
 | |
|     double rY = getHeight() / 2;
 | |
|     double centerX = getX() + rX;
 | |
|     double centerY = getY() + rY;
 | |
| 
 | |
|     Point2D p1 = getStartPoint();
 | |
|     Rectangle2D result = makeBounds(p1.getX(), p1.getY(), 0, 0);
 | |
|     result.add(getEndPoint());
 | |
| 
 | |
|     if (type == PIE)
 | |
|       result.add(centerX, centerY);
 | |
|     if (containsAngle(0))
 | |
|       result.add(centerX + rX, centerY);
 | |
|     if (containsAngle(90))
 | |
|       result.add(centerX, centerY - rY);
 | |
|     if (containsAngle(180))
 | |
|       result.add(centerX - rX, centerY);
 | |
|     if (containsAngle(270))
 | |
|       result.add(centerX, centerY + rY);
 | |
| 
 | |
|     return result;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Construct a bounding box in a precision appropriate for the subclass.
 | |
|    *
 | |
|    * @param x the x coordinate
 | |
|    * @param y the y coordinate
 | |
|    * @param w the width
 | |
|    * @param h the height
 | |
|    * @return the rectangle for use in getBounds2D
 | |
|    */
 | |
|   protected abstract Rectangle2D makeBounds(double x, double y, double w,
 | |
|                                             double h);
 | |
| 
 | |
|   /**
 | |
|    * Tests if the given angle, in degrees, is included in the arc.
 | |
|    * All angles are normalized to be between 0 and 360 degrees.
 | |
|    *
 | |
|    * @param a the angle to test
 | |
|    * @return true if it is contained
 | |
|    */
 | |
|   public boolean containsAngle(double a)
 | |
|   {
 | |
|     double start = getAngleStart();
 | |
|     double extent = getAngleExtent();
 | |
|     double end = start + extent;
 | |
| 
 | |
|     if (extent == 0)
 | |
|       return false;
 | |
| 
 | |
|     if (extent >= 360 || extent <= -360)
 | |
|       return true;
 | |
| 
 | |
|     if (extent < 0)
 | |
|       {
 | |
|         end = start;
 | |
|         start += extent;
 | |
|       }
 | |
| 
 | |
|     start %= 360;
 | |
|     while (start < 0)
 | |
|       start += 360;
 | |
| 
 | |
|     end %= 360;
 | |
|     while (end < start)
 | |
|       end += 360;
 | |
| 
 | |
|     a %= 360;
 | |
|     while (a < start)
 | |
|       a += 360;
 | |
| 
 | |
|     return a >= start && a < end; // starting angle included, ending angle not
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Determines if the arc contains the given point. If the bounding box
 | |
|    * is empty, then this will return false.
 | |
|    *
 | |
|    * The area considered 'inside' an arc of type OPEN is the same as the
 | |
|    * area inside an equivalent filled CHORD-type arc. The area considered
 | |
|    * 'inside' a CHORD-type arc is the same as the filled area.
 | |
|    *
 | |
|    * @param x the x coordinate to test
 | |
|    * @param y the y coordinate to test
 | |
|    * @return true if the point is inside the arc
 | |
|    */
 | |
|   public boolean contains(double x, double y)
 | |
|   {
 | |
|     double w = getWidth();
 | |
|     double h = getHeight();
 | |
|     double extent = getAngleExtent();
 | |
|     if (w <= 0 || h <= 0 || extent == 0)
 | |
|       return false;
 | |
| 
 | |
|     double mx = getX() + w / 2;
 | |
|     double my = getY() + h / 2;
 | |
|     double dx = (x - mx) * 2 / w;
 | |
|     double dy = (y - my) * 2 / h;
 | |
|     if ((dx * dx + dy * dy) >= 1.0)
 | |
|       return false;
 | |
| 
 | |
|     double angle = Math.toDegrees(Math.atan2(-dy, dx));
 | |
|     if (getArcType() == PIE)
 | |
|       return containsAngle(angle);
 | |
| 
 | |
|     double a1 = Math.toRadians(getAngleStart());
 | |
|     double a2 = Math.toRadians(getAngleStart() + extent);
 | |
|     double x1 = mx + getWidth() * Math.cos(a1) / 2;
 | |
|     double y1 = my - getHeight() * Math.sin(a1) / 2;
 | |
|     double x2 = mx + getWidth() * Math.cos(a2) / 2;
 | |
|     double y2 = my - getHeight() * Math.sin(a2) / 2;
 | |
|     double sgn = ((x2 - x1) * (my - y1) - (mx - x1) * (y2 - y1)) * ((x2 - x1) * (y
 | |
|                  - y1) - (x - x1) * (y2 - y1));
 | |
| 
 | |
|     if (Math.abs(extent) > 180)
 | |
|       {
 | |
|         if (containsAngle(angle))
 | |
|           return true;
 | |
|         return sgn > 0;
 | |
|       }
 | |
|     else
 | |
|       {
 | |
|         if (! containsAngle(angle))
 | |
|           return false;
 | |
|         return sgn < 0;
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Tests if a given rectangle intersects the area of the arc.
 | |
|    *
 | |
|    * For a definition of the 'inside' area, see the contains() method.
 | |
|    * @see #contains(double, double)
 | |
|    *
 | |
|    * @param x the x coordinate of the rectangle
 | |
|    * @param y the y coordinate of the rectangle
 | |
|    * @param w the width of the rectangle
 | |
|    * @param h the height of the rectangle
 | |
|    * @return true if the two shapes share common points
 | |
|    */
 | |
|   public boolean intersects(double x, double y, double w, double h)
 | |
|   {
 | |
|     double extent = getAngleExtent();
 | |
|     if (extent == 0)
 | |
|       return false;
 | |
| 
 | |
|     if (contains(x, y) || contains(x, y + h) || contains(x + w, y)
 | |
|         || contains(x + w, y + h))
 | |
|       return true;
 | |
| 
 | |
|     Rectangle2D rect = new Rectangle2D.Double(x, y, w, h);
 | |
| 
 | |
|     double a = getWidth() / 2.0;
 | |
|     double b = getHeight() / 2.0;
 | |
| 
 | |
|     double mx = getX() + a;
 | |
|     double my = getY() + b;
 | |
|     double x1 = mx + a * Math.cos(Math.toRadians(getAngleStart()));
 | |
|     double y1 = my - b * Math.sin(Math.toRadians(getAngleStart()));
 | |
|     double x2 = mx + a * Math.cos(Math.toRadians(getAngleStart() + extent));
 | |
|     double y2 = my - b * Math.sin(Math.toRadians(getAngleStart() + extent));
 | |
| 
 | |
|     if (getArcType() != CHORD)
 | |
|       {
 | |
|         // check intersections against the pie radii
 | |
|         if (rect.intersectsLine(mx, my, x1, y1))
 | |
|           return true;
 | |
|         if (rect.intersectsLine(mx, my, x2, y2))
 | |
|           return true;
 | |
|       }
 | |
|     else// check the chord
 | |
|     if (rect.intersectsLine(x1, y1, x2, y2))
 | |
|       return true;
 | |
| 
 | |
|     // Check the Arc segment against the four edges
 | |
|     double dx;
 | |
| 
 | |
|     // Check the Arc segment against the four edges
 | |
|     double dy;
 | |
|     dy = y - my;
 | |
|     dx = a * Math.sqrt(1 - ((dy * dy) / (b * b)));
 | |
|     if (! java.lang.Double.isNaN(dx))
 | |
|       {
 | |
|         if (mx + dx >= x && mx + dx <= x + w
 | |
|             && containsAngle(Math.toDegrees(Math.atan2(-dy, dx))))
 | |
|           return true;
 | |
|         if (mx - dx >= x && mx - dx <= x + w
 | |
|             && containsAngle(Math.toDegrees(Math.atan2(-dy, -dx))))
 | |
|           return true;
 | |
|       }
 | |
|     dy = (y + h) - my;
 | |
|     dx = a * Math.sqrt(1 - ((dy * dy) / (b * b)));
 | |
|     if (! java.lang.Double.isNaN(dx))
 | |
|       {
 | |
|         if (mx + dx >= x && mx + dx <= x + w
 | |
|             && containsAngle(Math.toDegrees(Math.atan2(-dy, dx))))
 | |
|           return true;
 | |
|         if (mx - dx >= x && mx - dx <= x + w
 | |
|             && containsAngle(Math.toDegrees(Math.atan2(-dy, -dx))))
 | |
|           return true;
 | |
|       }
 | |
|     dx = x - mx;
 | |
|     dy = b * Math.sqrt(1 - ((dx * dx) / (a * a)));
 | |
|     if (! java.lang.Double.isNaN(dy))
 | |
|       {
 | |
|         if (my + dy >= y && my + dy <= y + h
 | |
|             && containsAngle(Math.toDegrees(Math.atan2(-dy, dx))))
 | |
|           return true;
 | |
|         if (my - dy >= y && my - dy <= y + h
 | |
|             && containsAngle(Math.toDegrees(Math.atan2(dy, dx))))
 | |
|           return true;
 | |
|       }
 | |
| 
 | |
|     dx = (x + w) - mx;
 | |
|     dy = b * Math.sqrt(1 - ((dx * dx) / (a * a)));
 | |
|     if (! java.lang.Double.isNaN(dy))
 | |
|       {
 | |
|         if (my + dy >= y && my + dy <= y + h
 | |
|             && containsAngle(Math.toDegrees(Math.atan2(-dy, dx))))
 | |
|           return true;
 | |
|         if (my - dy >= y && my - dy <= y + h
 | |
|             && containsAngle(Math.toDegrees(Math.atan2(dy, dx))))
 | |
|           return true;
 | |
|       }
 | |
| 
 | |
|     // Check whether the arc is contained within the box
 | |
|     if (rect.contains(mx, my))
 | |
|       return true;
 | |
| 
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Tests if a given rectangle is contained in the area of the arc.
 | |
|    *
 | |
|    * @param x the x coordinate of the rectangle
 | |
|    * @param y the y coordinate of the rectangle
 | |
|    * @param w the width of the rectangle
 | |
|    * @param h the height of the rectangle
 | |
|    * @return true if the arc contains the rectangle
 | |
|    */
 | |
|   public boolean contains(double x, double y, double w, double h)
 | |
|   {
 | |
|     double extent = getAngleExtent();
 | |
|     if (extent == 0)
 | |
|       return false;
 | |
| 
 | |
|     if (! (contains(x, y) && contains(x, y + h) && contains(x + w, y)
 | |
|         && contains(x + w, y + h)))
 | |
|       return false;
 | |
| 
 | |
|     Rectangle2D rect = new Rectangle2D.Double(x, y, w, h);
 | |
| 
 | |
|     double a = getWidth() / 2.0;
 | |
|     double b = getHeight() / 2.0;
 | |
| 
 | |
|     double mx = getX() + a;
 | |
|     double my = getY() + b;
 | |
|     double x1 = mx + a * Math.cos(Math.toRadians(getAngleStart()));
 | |
|     double y1 = my - b * Math.sin(Math.toRadians(getAngleStart()));
 | |
|     double x2 = mx + a * Math.cos(Math.toRadians(getAngleStart() + extent));
 | |
|     double y2 = my - b * Math.sin(Math.toRadians(getAngleStart() + extent));
 | |
|     if (getArcType() != CHORD)
 | |
|       {
 | |
|         // check intersections against the pie radii
 | |
|         if (rect.intersectsLine(mx, my, x1, y1))
 | |
|           return false;
 | |
| 
 | |
|         if (rect.intersectsLine(mx, my, x2, y2))
 | |
|           return false;
 | |
|       }
 | |
|     else if (rect.intersectsLine(x1, y1, x2, y2))
 | |
|       return false;
 | |
|     return true;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Tests if a given rectangle is contained in the area of the arc.
 | |
|    *
 | |
|    * @param r the rectangle
 | |
|    * @return true if the arc contains the rectangle
 | |
|    */
 | |
|   public boolean contains(Rectangle2D r)
 | |
|   {
 | |
|     return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns an iterator over this arc, with an optional transformation.
 | |
|    * This iterator is threadsafe, so future modifications to the arc do not
 | |
|    * affect the iteration.
 | |
|    *
 | |
|    * @param at the transformation, or null
 | |
|    * @return a path iterator
 | |
|    */
 | |
|   public PathIterator getPathIterator(AffineTransform at)
 | |
|   {
 | |
|     return new ArcIterator(this, at);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * This class is used to iterate over an arc. Since ellipses are a subclass
 | |
|    * of arcs, this is used by Ellipse2D as well.
 | |
|    *
 | |
|    * @author Eric Blake (ebb9@email.byu.edu)
 | |
|    */
 | |
|   static final class ArcIterator implements PathIterator
 | |
|   {
 | |
|     /** The current iteration. */
 | |
|     private int current;
 | |
| 
 | |
|     /** The last iteration. */
 | |
|     private final int limit;
 | |
| 
 | |
|     /** The optional transformation. */
 | |
|     private final AffineTransform xform;
 | |
| 
 | |
|     /** The x coordinate of the bounding box. */
 | |
|     private final double x;
 | |
| 
 | |
|     /** The y coordinate of the bounding box. */
 | |
|     private final double y;
 | |
| 
 | |
|     /** The width of the bounding box. */
 | |
|     private final double w;
 | |
| 
 | |
|     /** The height of the bounding box. */
 | |
|     private final double h;
 | |
| 
 | |
|     /** The start angle, in radians (not degrees). */
 | |
|     private final double start;
 | |
| 
 | |
|     /** The extent angle, in radians (not degrees). */
 | |
|     private final double extent;
 | |
| 
 | |
|     /** The arc closure type. */
 | |
|     private final int type;
 | |
| 
 | |
|     /**
 | |
|      * Construct a new iterator over an arc.
 | |
|      *
 | |
|      * @param a the arc
 | |
|      * @param xform the transform
 | |
|      */
 | |
|     public ArcIterator(Arc2D a, AffineTransform xform)
 | |
|     {
 | |
|       this.xform = xform;
 | |
|       x = a.getX();
 | |
|       y = a.getY();
 | |
|       w = a.getWidth();
 | |
|       h = a.getHeight();
 | |
|       double start = Math.toRadians(a.getAngleStart());
 | |
|       double extent = Math.toRadians(a.getAngleExtent());
 | |
| 
 | |
|       this.start = start;
 | |
|       this.extent = extent;
 | |
| 
 | |
|       type = a.type;
 | |
|       if (w < 0 || h < 0)
 | |
|         limit = -1;
 | |
|       else if (extent == 0)
 | |
|         limit = type;
 | |
|       else if (Math.abs(extent) <= Math.PI / 2.0)
 | |
|         limit = type + 1;
 | |
|       else if (Math.abs(extent) <= Math.PI)
 | |
|         limit = type + 2;
 | |
|       else if (Math.abs(extent) <= 3.0 * (Math.PI / 2.0))
 | |
|         limit = type + 3;
 | |
|       else
 | |
|         limit = type + 4;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Construct a new iterator over an ellipse.
 | |
|      *
 | |
|      * @param e the ellipse
 | |
|      * @param xform the transform
 | |
|      */
 | |
|     public ArcIterator(Ellipse2D e, AffineTransform xform)
 | |
|     {
 | |
|       this.xform = xform;
 | |
|       x = e.getX();
 | |
|       y = e.getY();
 | |
|       w = e.getWidth();
 | |
|       h = e.getHeight();
 | |
|       start = 0;
 | |
|       extent = 2 * Math.PI;
 | |
|       type = CHORD;
 | |
|       limit = (w < 0 || h < 0) ? -1 : 5;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Return the winding rule.
 | |
|      *
 | |
|      * @return {@link PathIterator#WIND_NON_ZERO}
 | |
|      */
 | |
|     public int getWindingRule()
 | |
|     {
 | |
|       return WIND_NON_ZERO;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Test if the iteration is complete.
 | |
|      *
 | |
|      * @return true if more segments exist
 | |
|      */
 | |
|     public boolean isDone()
 | |
|     {
 | |
|       return current > limit;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Advance the iterator.
 | |
|      */
 | |
|     public void next()
 | |
|     {
 | |
|       current++;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Put the current segment into the array, and return the segment type.
 | |
|      *
 | |
|      * @param coords an array of 6 elements
 | |
|      * @return the segment type
 | |
|      * @throws NullPointerException if coords is null
 | |
|      * @throws ArrayIndexOutOfBoundsException if coords is too small
 | |
|      */
 | |
|     public int currentSegment(float[] coords)
 | |
|     {
 | |
|       double[] double_coords = new double[6];
 | |
|       int code = currentSegment(double_coords);
 | |
|       for (int i = 0; i < 6; ++i)
 | |
|         coords[i] = (float) double_coords[i];
 | |
|       return code;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Put the current segment into the array, and return the segment type.
 | |
|      *
 | |
|      * @param coords an array of 6 elements
 | |
|      * @return the segment type
 | |
|      * @throws NullPointerException if coords is null
 | |
|      * @throws ArrayIndexOutOfBoundsException if coords is too small
 | |
|      */
 | |
|     public int currentSegment(double[] coords)
 | |
|     {
 | |
|       double rx = w / 2;
 | |
|       double ry = h / 2;
 | |
|       double xmid = x + rx;
 | |
|       double ymid = y + ry;
 | |
| 
 | |
|       if (current > limit)
 | |
|         throw new NoSuchElementException("arc iterator out of bounds");
 | |
| 
 | |
|       if (current == 0)
 | |
|         {
 | |
|           coords[0] = xmid + rx * Math.cos(start);
 | |
|           coords[1] = ymid - ry * Math.sin(start);
 | |
|           if (xform != null)
 | |
|             xform.transform(coords, 0, coords, 0, 1);
 | |
|           return SEG_MOVETO;
 | |
|         }
 | |
| 
 | |
|       if (type != OPEN && current == limit)
 | |
|         return SEG_CLOSE;
 | |
| 
 | |
|       if ((current == limit - 1) && (type == PIE))
 | |
|         {
 | |
|           coords[0] = xmid;
 | |
|           coords[1] = ymid;
 | |
|           if (xform != null)
 | |
|             xform.transform(coords, 0, coords, 0, 1);
 | |
|           return SEG_LINETO;
 | |
|         }
 | |
| 
 | |
|       // note that this produces a cubic approximation of the arc segment,
 | |
|       // not a true ellipsoid. there's no ellipsoid path segment code,
 | |
|       // unfortunately. the cubic approximation looks about right, though.
 | |
|       double kappa = (Math.sqrt(2.0) - 1.0) * (4.0 / 3.0);
 | |
|       double quad = (Math.PI / 2.0);
 | |
| 
 | |
|       double curr_begin;
 | |
|       double curr_extent;
 | |
|       if (extent > 0)
 | |
|         {
 | |
|           curr_begin = start + (current - 1) * quad;
 | |
|           curr_extent = Math.min((start + extent) - curr_begin, quad);
 | |
|         }
 | |
|       else
 | |
|         {
 | |
|           curr_begin = start - (current - 1) * quad;
 | |
|           curr_extent = Math.max((start + extent) - curr_begin, -quad);
 | |
|         }
 | |
| 
 | |
|       double portion_of_a_quadrant = Math.abs(curr_extent / quad);
 | |
| 
 | |
|       double x0 = xmid + rx * Math.cos(curr_begin);
 | |
|       double y0 = ymid - ry * Math.sin(curr_begin);
 | |
| 
 | |
|       double x1 = xmid + rx * Math.cos(curr_begin + curr_extent);
 | |
|       double y1 = ymid - ry * Math.sin(curr_begin + curr_extent);
 | |
| 
 | |
|       AffineTransform trans = new AffineTransform();
 | |
|       double[] cvec = new double[2];
 | |
|       double len = kappa * portion_of_a_quadrant;
 | |
|       double angle = curr_begin;
 | |
| 
 | |
|       // in a hypothetical "first quadrant" setting, our first control
 | |
|       // vector would be sticking up, from [1,0] to [1,kappa].
 | |
|       //
 | |
|       // let us recall however that in java2d, y coords are upside down
 | |
|       // from what one would consider "normal" first quadrant rules, so we
 | |
|       // will *subtract* the y value of this control vector from our first
 | |
|       // point.
 | |
|       cvec[0] = 0;
 | |
|       if (extent > 0)
 | |
|         cvec[1] = len;
 | |
|       else
 | |
|         cvec[1] = -len;
 | |
| 
 | |
|       trans.scale(rx, ry);
 | |
|       trans.rotate(angle);
 | |
|       trans.transform(cvec, 0, cvec, 0, 1);
 | |
|       coords[0] = x0 + cvec[0];
 | |
|       coords[1] = y0 - cvec[1];
 | |
| 
 | |
|       // control vector #2 would, ideally, be sticking out and to the
 | |
|       // right, in a first quadrant arc segment. again, subtraction of y.
 | |
|       cvec[0] = 0;
 | |
|       if (extent > 0)
 | |
|         cvec[1] = -len;
 | |
|       else
 | |
|         cvec[1] = len;
 | |
| 
 | |
|       trans.rotate(curr_extent);
 | |
|       trans.transform(cvec, 0, cvec, 0, 1);
 | |
|       coords[2] = x1 + cvec[0];
 | |
|       coords[3] = y1 - cvec[1];
 | |
| 
 | |
|       // end point
 | |
|       coords[4] = x1;
 | |
|       coords[5] = y1;
 | |
| 
 | |
|       if (xform != null)
 | |
|         xform.transform(coords, 0, coords, 0, 3);
 | |
| 
 | |
|       return SEG_CUBICTO;
 | |
|     }
 | |
|   } // class ArcIterator
 | |
| 
 | |
|   /**
 | |
|    * This class implements an arc in double precision.
 | |
|    *
 | |
|    * @author Eric Blake (ebb9@email.byu.edu)
 | |
|    * @since 1.2
 | |
|    */
 | |
|   public static class Double extends Arc2D
 | |
|   {
 | |
|     /** The x coordinate of the box bounding the ellipse of this arc. */
 | |
|     public double x;
 | |
| 
 | |
|     /** The y coordinate of the box bounding the ellipse of this arc. */
 | |
|     public double y;
 | |
| 
 | |
|     /** The width of the box bounding the ellipse of this arc. */
 | |
|     public double width;
 | |
| 
 | |
|     /** The height of the box bounding the ellipse of this arc. */
 | |
|     public double height;
 | |
| 
 | |
|     /** The start angle of this arc, in degrees. */
 | |
|     public double start;
 | |
| 
 | |
|     /** The extent angle of this arc, in degrees. */
 | |
|     public double extent;
 | |
| 
 | |
|     /**
 | |
|      * Create a new, open arc at (0,0) with 0 extent.
 | |
|      */
 | |
|     public Double()
 | |
|     {
 | |
|       super(OPEN);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Create a new arc of the given type at (0,0) with 0 extent.
 | |
|      *
 | |
|      * @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE}
 | |
|      * @throws IllegalArgumentException if type is invalid
 | |
|      */
 | |
|     public Double(int type)
 | |
|     {
 | |
|       super(type);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Create a new arc with the given dimensions.
 | |
|      *
 | |
|      * @param x the x coordinate
 | |
|      * @param y the y coordinate
 | |
|      * @param w the width
 | |
|      * @param h the height
 | |
|      * @param start the start angle, in degrees
 | |
|      * @param extent the extent, in degrees
 | |
|      * @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE}
 | |
|      * @throws IllegalArgumentException if type is invalid
 | |
|      */
 | |
|     public Double(double x, double y, double w, double h, double start,
 | |
|                   double extent, int type)
 | |
|     {
 | |
|       super(type);
 | |
|       this.x = x;
 | |
|       this.y = y;
 | |
|       width = w;
 | |
|       height = h;
 | |
|       this.start = start;
 | |
|       this.extent = extent;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Create a new arc with the given dimensions.
 | |
|      *
 | |
|      * @param r the bounding box
 | |
|      * @param start the start angle, in degrees
 | |
|      * @param extent the extent, in degrees
 | |
|      * @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE}
 | |
|      * @throws IllegalArgumentException if type is invalid
 | |
|      * @throws NullPointerException if r is null
 | |
|      */
 | |
|     public Double(Rectangle2D r, double start, double extent, int type)
 | |
|     {
 | |
|       super(type);
 | |
|       x = r.getX();
 | |
|       y = r.getY();
 | |
|       width = r.getWidth();
 | |
|       height = r.getHeight();
 | |
|       this.start = start;
 | |
|       this.extent = extent;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Return the x coordinate of the bounding box.
 | |
|      *
 | |
|      * @return the value of x
 | |
|      */
 | |
|     public double getX()
 | |
|     {
 | |
|       return x;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Return the y coordinate of the bounding box.
 | |
|      *
 | |
|      * @return the value of y
 | |
|      */
 | |
|     public double getY()
 | |
|     {
 | |
|       return y;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Return the width of the bounding box.
 | |
|      *
 | |
|      * @return the value of width
 | |
|      */
 | |
|     public double getWidth()
 | |
|     {
 | |
|       return width;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Return the height of the bounding box.
 | |
|      *
 | |
|      * @return the value of height
 | |
|      */
 | |
|     public double getHeight()
 | |
|     {
 | |
|       return height;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Return the start angle of the arc, in degrees.
 | |
|      *
 | |
|      * @return the value of start
 | |
|      */
 | |
|     public double getAngleStart()
 | |
|     {
 | |
|       return start;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Return the extent of the arc, in degrees.
 | |
|      *
 | |
|      * @return the value of extent
 | |
|      */
 | |
|     public double getAngleExtent()
 | |
|     {
 | |
|       return extent;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Tests if the arc contains points.
 | |
|      *
 | |
|      * @return true if the arc has no interior
 | |
|      */
 | |
|     public boolean isEmpty()
 | |
|     {
 | |
|       return width <= 0 || height <= 0;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Sets the arc to the given dimensions.
 | |
|      *
 | |
|      * @param x the x coordinate
 | |
|      * @param y the y coordinate
 | |
|      * @param w the width
 | |
|      * @param h the height
 | |
|      * @param start the start angle, in degrees
 | |
|      * @param extent the extent, in degrees
 | |
|      * @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE}
 | |
|      * @throws IllegalArgumentException if type is invalid
 | |
|      */
 | |
|     public void setArc(double x, double y, double w, double h, double start,
 | |
|                        double extent, int type)
 | |
|     {
 | |
|       this.x = x;
 | |
|       this.y = y;
 | |
|       width = w;
 | |
|       height = h;
 | |
|       this.start = start;
 | |
|       this.extent = extent;
 | |
|       setArcType(type);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Sets the start angle of the arc.
 | |
|      *
 | |
|      * @param start the new start angle
 | |
|      */
 | |
|     public void setAngleStart(double start)
 | |
|     {
 | |
|       this.start = start;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Sets the extent angle of the arc.
 | |
|      *
 | |
|      * @param extent the new extent angle
 | |
|      */
 | |
|     public void setAngleExtent(double extent)
 | |
|     {
 | |
|       this.extent = extent;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Creates a tight bounding box given dimensions that more precise than
 | |
|      * the bounding box of the ellipse.
 | |
|      *
 | |
|      * @param x the x coordinate
 | |
|      * @param y the y coordinate
 | |
|      * @param w the width
 | |
|      * @param h the height
 | |
|      */
 | |
|     protected Rectangle2D makeBounds(double x, double y, double w, double h)
 | |
|     {
 | |
|       return new Rectangle2D.Double(x, y, w, h);
 | |
|     }
 | |
|   } // class Double
 | |
| 
 | |
|   /**
 | |
|    * This class implements an arc in float precision.
 | |
|    *
 | |
|    * @author Eric Blake (ebb9@email.byu.edu)
 | |
|    * @since 1.2
 | |
|    */
 | |
|   public static class Float extends Arc2D
 | |
|   {
 | |
|     /** The x coordinate of the box bounding the ellipse of this arc. */
 | |
|     public float x;
 | |
| 
 | |
|     /** The y coordinate of the box bounding the ellipse of this arc. */
 | |
|     public float y;
 | |
| 
 | |
|     /** The width of the box bounding the ellipse of this arc. */
 | |
|     public float width;
 | |
| 
 | |
|     /** The height of the box bounding the ellipse of this arc. */
 | |
|     public float height;
 | |
| 
 | |
|     /** The start angle of this arc, in degrees. */
 | |
|     public float start;
 | |
| 
 | |
|     /** The extent angle of this arc, in degrees. */
 | |
|     public float extent;
 | |
| 
 | |
|     /**
 | |
|      * Create a new, open arc at (0,0) with 0 extent.
 | |
|      */
 | |
|     public Float()
 | |
|     {
 | |
|       super(OPEN);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Create a new arc of the given type at (0,0) with 0 extent.
 | |
|      *
 | |
|      * @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE}
 | |
|      * @throws IllegalArgumentException if type is invalid
 | |
|      */
 | |
|     public Float(int type)
 | |
|     {
 | |
|       super(type);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Create a new arc with the given dimensions.
 | |
|      *
 | |
|      * @param x the x coordinate
 | |
|      * @param y the y coordinate
 | |
|      * @param w the width
 | |
|      * @param h the height
 | |
|      * @param start the start angle, in degrees
 | |
|      * @param extent the extent, in degrees
 | |
|      * @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE}
 | |
|      * @throws IllegalArgumentException if type is invalid
 | |
|      */
 | |
|     public Float(float x, float y, float w, float h, float start,
 | |
|                  float extent, int type)
 | |
|     {
 | |
|       super(type);
 | |
|       this.x = x;
 | |
|       this.y = y;
 | |
|       width = w;
 | |
|       height = h;
 | |
|       this.start = start;
 | |
|       this.extent = extent;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Create a new arc with the given dimensions.
 | |
|      *
 | |
|      * @param r the bounding box
 | |
|      * @param start the start angle, in degrees
 | |
|      * @param extent the extent, in degrees
 | |
|      * @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE}
 | |
|      * @throws IllegalArgumentException if type is invalid
 | |
|      * @throws NullPointerException if r is null
 | |
|      */
 | |
|     public Float(Rectangle2D r, float start, float extent, int type)
 | |
|     {
 | |
|       super(type);
 | |
|       x = (float) r.getX();
 | |
|       y = (float) r.getY();
 | |
|       width = (float) r.getWidth();
 | |
|       height = (float) r.getHeight();
 | |
|       this.start = start;
 | |
|       this.extent = extent;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Return the x coordinate of the bounding box.
 | |
|      *
 | |
|      * @return the value of x
 | |
|      */
 | |
|     public double getX()
 | |
|     {
 | |
|       return x;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Return the y coordinate of the bounding box.
 | |
|      *
 | |
|      * @return the value of y
 | |
|      */
 | |
|     public double getY()
 | |
|     {
 | |
|       return y;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Return the width of the bounding box.
 | |
|      *
 | |
|      * @return the value of width
 | |
|      */
 | |
|     public double getWidth()
 | |
|     {
 | |
|       return width;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Return the height of the bounding box.
 | |
|      *
 | |
|      * @return the value of height
 | |
|      */
 | |
|     public double getHeight()
 | |
|     {
 | |
|       return height;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Return the start angle of the arc, in degrees.
 | |
|      *
 | |
|      * @return the value of start
 | |
|      */
 | |
|     public double getAngleStart()
 | |
|     {
 | |
|       return start;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Return the extent of the arc, in degrees.
 | |
|      *
 | |
|      * @return the value of extent
 | |
|      */
 | |
|     public double getAngleExtent()
 | |
|     {
 | |
|       return extent;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Tests if the arc contains points.
 | |
|      *
 | |
|      * @return true if the arc has no interior
 | |
|      */
 | |
|     public boolean isEmpty()
 | |
|     {
 | |
|       return width <= 0 || height <= 0;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Sets the arc to the given dimensions.
 | |
|      *
 | |
|      * @param x the x coordinate
 | |
|      * @param y the y coordinate
 | |
|      * @param w the width
 | |
|      * @param h the height
 | |
|      * @param start the start angle, in degrees
 | |
|      * @param extent the extent, in degrees
 | |
|      * @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE}
 | |
|      * @throws IllegalArgumentException if type is invalid
 | |
|      */
 | |
|     public void setArc(double x, double y, double w, double h, double start,
 | |
|                        double extent, int type)
 | |
|     {
 | |
|       this.x = (float) x;
 | |
|       this.y = (float) y;
 | |
|       width = (float) w;
 | |
|       height = (float) h;
 | |
|       this.start = (float) start;
 | |
|       this.extent = (float) extent;
 | |
|       setArcType(type);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Sets the start angle of the arc.
 | |
|      *
 | |
|      * @param start the new start angle
 | |
|      */
 | |
|     public void setAngleStart(double start)
 | |
|     {
 | |
|       this.start = (float) start;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Sets the extent angle of the arc.
 | |
|      *
 | |
|      * @param extent the new extent angle
 | |
|      */
 | |
|     public void setAngleExtent(double extent)
 | |
|     {
 | |
|       this.extent = (float) extent;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Creates a tight bounding box given dimensions that more precise than
 | |
|      * the bounding box of the ellipse.
 | |
|      *
 | |
|      * @param x the x coordinate
 | |
|      * @param y the y coordinate
 | |
|      * @param w the width
 | |
|      * @param h the height
 | |
|      */
 | |
|     protected Rectangle2D makeBounds(double x, double y, double w, double h)
 | |
|     {
 | |
|       return new Rectangle2D.Float((float) x, (float) y, (float) w, (float) h);
 | |
|     }
 | |
|   } // class Float
 | |
| } // class Arc2D
 |