// Implements a simple arc class // (c) 1997 duane a. bailey package element; /** * An object that describes a portion of an oval. * * @version $Id: Arc.java,v 2.2 1999/08/05 16:18:01 bailey Exp bailey $ * @author duane a. bailey */ public class Arc extends Oval { /** * The start angle of the arc. Measured in degrees, with zero degrees * due right, and increasing counter-clockwize. */ protected int start; /** * The span of the arc, increasing counter-clockwize from the start angle. */ protected int angle; /** * Construct a trivial arc located at the origin. * */ public Arc() // post: constructs a circle at origin { this(0,0,0,0,0,360); } /** * Construct an oval determined by two points: p and q. * @param p one of the two points determining the bounding rectangle * @param q the other point determining the bounding rectangle */ public Arc(Pt p, Pt q) // pre: p and q are valid points // post: constructs oval bounded by p and q { super(p,q); // construct the containing rectangle start = 0; angle = 360; } /** * Construct an arc bounded by rectangle r with specified start and sweep. * * @param r the bounding rectangle * @param strt the starting angle of the arc * @param angl the counter-clockwize sweep of the arc. */ public Arc(Rect r, int strt, int angl) // post: constructs an arc bounded by r, // swept for angl degrees, starting at strt { this(r.left(),r.top(),r.width(),r.height(),strt,angl); } /** * Construct an arc bounded by the rectangle specified by (x,y,w,h), starting * at strt, and sweeping for angl degrees. * * @param x the left side of the bounding rectangle. * @param y the top side of the bounding rectangle * @param w the width of the bounding rectangle * @param h the height of the bounding rectangle * @param strt the starting angle of the arc, with zero pointing due right * @param angl the size of counter-clockwize sweep of arc. */ public Arc(int x, int y, int w, int h, int strt, int angl) // pre: w >= 0, h >= 0 // post: constructs arc with top left at (x,y), width w, // height h, and sweep angl from starting angle strt { super(x,y,w,h); if (angle < 0) { angle = -angle; start -= angle; } start = canonical(strt); angle = angl; } /** * Construct an oval bounded by the rectangle specified by (x,y,w,h). * * @param x the left side of the bounding rectangle. * @param y the top side of the bounding rectangle * @param w the width of the bounding rectangle * @param h the height of the bounding rectangle */ public Arc(int x, int y, int w, int h) // pre: w >= 0, h >= 0 // post: constructs an oval with top left at (x,y), // width w, height h { super(x,y,w,h); start = 0; angle = 360; } /** * Constructs a copy of an arc from another. * * @param r the source arc. */ public Arc(Arc r) // pre: r is a valid arc // post: this is a copy of r { this(r.left(),r.top(),r.width(),r.height(),r.start,r.angle); } /** * turn an angle into one that is between 0 and 359. * * @param angle the initial angle. * @return the canonical form of the angle. */ protected static int canonical(int angle) // post: reduces an angle to a value between 0 and 359 { // this can be simplified... return (360+(angle-(360*(angle/360))))%360; } /** * Determine if a point p is within an arc. * * @param p the point to be checked * @return true if the point is within the arc, false otherwise. */ public boolean contains(Pt p) // post: returns true iff p is within confines of the arc { if (!super.contains(p)) return false; int cx = left() + width()/2; int cy = top() + height()/2; int dx = p.x()-cx; int dy = cy-p.y(); // screen is upside down... double theta = Math.atan2((double)dy,(double)dx); int degrees = canonical((int)(theta*180.0/Math.PI)); return canonical(degrees-start) <= angle; } /** * Return the starting angle of the arc. * @return the starting angle of the arc. */ public int start() // post: returns the starting angle of the arc { return start; } /** * Return the span of the arc. * @return the span of the arc, in degrees. */ public int angle() // post: returns the span of the arc, in degrees { return angle; } /** * Set the starting angle of the arc. * @param strt the new starting angle of the arc, in degrees. */ public void start(int strt) // pre: strt is an angle // post: arc is rotated to start at angle strt { start = canonical(strt); } /** * Set the span or sweep of the arc. * @param angl the sweep of the arc, in degrees, counter-clockwize from start. */ public void angle(int angl) // pre: angl is a sweep, in degrees // post: the angle is changed to sweep out angle degrees { angle = angl; } /** * Draw this arc on the specified drawing window. * * @param d the target drawing window. * @see element.DrawingWindow#fill * @see element.DrawingWindow#paintMode * @see element.DrawingWindow#invertMode */ public void fillOn(DrawingWindow d) // pre: d is a valid drawing window // post: the arc is filled on the drawing window d { d.fillArc(left,top,width,height,start,angle); } /** * Erase arc from the drawing window d. * * @param d the target drawing window * @see element.DrawingWindow#clear */ public void clearOn(DrawingWindow d) // pre: d is a valid drawing window // post: the arc is erased from the drawing window { d.clearArc(left,top,width,height,start,angle); } /** * Draw (in the current mode) the arc on the drawing window. * @param d the target drawing window * @see element.DrawingWindow#paintMode * @see element.DrawingWindow#invertMode * @see element.DrawingWindow#draw */ public void drawOn(DrawingWindow d) // pre: d is a valid drawing window // post: the arc is drawn on the drawing window { d.drawArc(left,top,width,height,start,angle); } /** * Return an integer for use as a hash code. * * @return a hash code */ public int hashCode() // post: returns a hash code { return left+top+width+height+start+angle; } /** * Return true iff this arc equals the other * * @param other another valid arc * @return true if the two are equal valued, false otherwise */ public boolean equals(Object other) // post: returns true iff two arcs are equal { Arc that = (Arc)other; return (this.left == that.left) && (this.top == that.top) && (this.width == that.width) && (this.height == that.height) && (this.start == that.start) && (this.angle == that.angle); } /** * return a distinct copy of this arc * * @return a distinct copy of this arc */ public Object clone() // post: returns a distinct copy of the arc { return new Arc(this); } /** * Construct a string representation of this arc * * @return a string representation of this arc */ public String toString() // post: returns a string representation of this arc { return ""; } }