KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > awt > geom > Arc2D


1 /*
2  * @(#)Arc2D.java 1.27 03/12/19
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package java.awt.geom;
9
10 /**
11  * <CODE>Arc2D</CODE> is the abstract superclass for all objects that
12  * store a 2D arc defined by a bounding rectangle,
13  * start angle, angular extent (length of the arc), and a closure type
14  * (<CODE>OPEN</CODE>, <CODE>CHORD</CODE>, or <CODE>PIE</CODE>).
15  * <p>
16  * The bounding rectangle defines the outer boundary of the full ellipse
17  * of which this arc is a partial section.
18  * The angles are specified relative to the non-square extents of the
19  * bounding rectangle such that 45 degrees always falls on the line from
20  * the center of the ellipse to the upper right corner of the bounding
21  * rectangle.
22  * As a result, if the bounding rectangle is noticeably longer along one
23  * axis than the other, the angles to the start and end of the arc segment
24  * will be skewed farther along the longer axis of the bounds.
25  * <p>
26  * The actual storage representation of the coordinates is left to
27  * the subclass.
28  *
29  * @version 10 Feb 1997
30  * @author Jim Graham
31  */

32 public abstract class Arc2D extends RectangularShape JavaDoc {
33     /**
34      * The closure type for an open arc with no path segments
35      * connecting the two ends of the arc segment.
36      */

37     public final static int OPEN = 0;
38
39     /**
40      * The closure type for an arc closed by drawing a straight
41      * line segment from the start of the arc segment to the end of the
42      * arc segment.
43      */

44     public final static int CHORD = 1;
45
46     /**
47      * The closure type for an arc closed by drawing straight line
48      * segments from the start of the arc segment to the center
49      * of the full ellipse and from that point to the end of the arc segment.
50      */

51     public final static int PIE = 2;
52
53     /**
54      * This class defines an arc specified in float precision.
55      */

56     public static class Float extends Arc2D JavaDoc {
57  
58         /**
59          * The x coordinate of the upper left corner of the arc.
60          */

61     public float x;
62
63         /**
64          * The y coordinate of the upper left corner of the arc.
65          */

66     public float y;
67
68         /**
69          * The overall width of the full ellipse of which this arc is
70          * a partial section (not considering the
71          * angular extents).
72          */

73     public float width;
74
75         /**
76          * The overall height of the full ellipse of which this arc is
77          * a partial section (not considering the
78          * angular extents).
79          */

80     public float height;
81
82         /**
83          * The starting angle of the arc in degrees.
84          */

85     public float start;
86
87         /**
88          * The angular extent of the arc in degrees.
89          */

90     public float extent;
91
92         /**
93          * Constructs a new OPEN arc, initialized to location (0, 0),
94          * size (0, 0), angular extents (start = 0, extent = 0).
95          */

96     public Float() {
97         super(OPEN);
98     }
99
100         /**
101          * Constructs a new arc, initialized to location (0, 0),
102          * size (0, 0), angular extents (start = 0, extent = 0), and
103          * the specified closure type.
104          *
105          * @param type The closure type for the arc:
106          * {@link #OPEN OPEN}, {@link #CHORD CHORD}, or {@link #PIE PIE}.
107          */

108     public Float(int type) {
109         super(type);
110     }
111
112         /**
113          * Constructs a new arc, initialized to the specified location,
114          * size, angular extents, and closure type.
115          *
116          * @param x,&nbsp;y The coordinates of the upper left corner of
117          * the arc. (Specified in float precision.)
118          * @param w The overall width of the full ellipse of which
119          * this arc is a partial section. (Specified in float precision.)
120          * @param h The overall height of the full ellipse of which this
121          * arc is a partial section. (Specified in float precision.)
122          * @param start The starting angle of the arc in degrees.
123          * (Specified in float precision.)
124          * @param extent The angular extent of the arc in degrees.
125          * (Specified in float precision.)
126          * @param type The closure type for the arc:
127          * {@link #OPEN OPEN}, {@link #CHORD CHORD}, or {@link #PIE PIE}.
128          */

129     public Float(float x, float y, float w, float h,
130              float start, float extent, int type) {
131         super(type);
132         this.x = x;
133         this.y = y;
134         this.width = w;
135         this.height = h;
136         this.start = start;
137         this.extent = extent;
138     }
139
140         /**
141          * Constructs a new arc, initialized to the specified location,
142          * size, angular extents, and closure type.
143          *
144          * @param ellipseBounds The bounding rectangle that defines the
145          * outer boundary of the full ellipse of which this arc is a
146          * partial section.
147          * @param start The starting angle of the arc in degrees.
148          * (Specified in float precision.)
149          * @param extent The angular extent of the arc in degrees.
150          * (Specified in float precision.)
151          * @param type The closure type for the arc:
152          * {@link #OPEN OPEN}, {@link #CHORD CHORD}, or {@link #PIE PIE}.
153          */

154     public Float(Rectangle2D JavaDoc ellipseBounds,
155              float start, float extent, int type) {
156         super(type);
157         this.x = (float) ellipseBounds.getX();
158         this.y = (float) ellipseBounds.getY();
159         this.width = (float) ellipseBounds.getWidth();
160         this.height = (float) ellipseBounds.getHeight();
161         this.start = start;
162         this.extent = extent;
163     }
164
165         /**
166          * Returns the x coordinate of the upper left corner of the arc.
167          *
168          * @return The x coordinate of arc's upper left coordinate in
169          * double precision.
170          */

171     public double getX() {
172         return (double) x;
173     }
174
175         /**
176          * Returns the y coordinate of the upper left corner of the arc.
177          *
178          * @return The y coordinate of arc's upper left coordinate in
179          * double precision.
180          */

181     public double getY() {
182         return (double) y;
183     }
184
185         /**
186          * Returns the width of the ellipse of which this arc is
187          * a partial section.
188          *
189          * @return A double value that represents the width of the full
190          * ellipse of which this arc is a partial section.
191          */

192     public double getWidth() {
193         return (double) width;
194     }
195
196         /**
197          * Returns the height of the ellipse of which this arc is
198          * a partial section.
199          *
200          * @return A double value that represents the height of the full
201          * ellipse of which this arc is a partial section.
202          */

203     public double getHeight() {
204         return (double) height;
205     }
206
207         /**
208          * Returns the starting angle of the arc.
209          *
210          * @return A double value that represents the starting angle of
211          * the arc in degrees.
212      * @see #setAngleStart
213          */

214     public double getAngleStart() {
215         return (double) start;
216     }
217
218         /**
219          * Returns the angular extent of the arc.
220          *
221          * @return A double value that represents the angular extent of
222          * the arc in degrees.
223      * @see #setAngleExtent
224          */

225     public double getAngleExtent() {
226         return (double) extent;
227     }
228
229         /**
230          * Determines whether the arc is empty.
231          *
232          * @return <CODE>true</CODE> if the arc is empty, <CODE>false</CODE>
233          * if it is not.
234          */

235     public boolean isEmpty() {
236         return (width <= 0.0 || height <= 0.0);
237     }
238
239         /**
240          * Sets the location, size, angular extents, and closure type of
241          * this arc to the specified double values.
242          *
243          * @param x,&nbsp;y The coordinates of the upper left corner of
244          * the arc.
245          * @param w The overall width of the full ellipse of which this
246          * arc is a partial section.
247          * @param h The overall height of the full ellipse of which this
248          * arc is a partial section.
249          * @param angSt The starting angle of the arc in degrees.
250          * @param angExt The angular extent of the arc in degrees.
251          * @param closure The closure type for the arc:
252          * {@link #OPEN OPEN}, {@link #CHORD CHORD}, or {@link #PIE PIE}.
253          */

254     public void setArc(double x, double y, double w, double h,
255                double angSt, double angExt, int closure) {
256         this.setArcType(closure);
257         this.x = (float) x;
258         this.y = (float) y;
259         this.width = (float) w;
260         this.height = (float) h;
261         this.start = (float) angSt;
262         this.extent = (float) angExt;
263     }
264
265         /**
266          * Sets the starting angle of this arc to the specified double
267          * value.
268          *
269          * @param angSt The starting angle of the arc in degrees.
270      * @see #getAngleStart
271          */

272     public void setAngleStart(double angSt) {
273         this.start = (float) angSt;
274     }
275
276         /**
277          * Sets the angular extent of this arc to the specified double
278          * value.
279          *
280          * @param angExt The angular extent of the arc in degrees.
281      * @see #getAngleExtent
282          */

283     public void setAngleExtent(double angExt) {
284         this.extent = (float) angExt;
285     }
286
287         /**
288          * Return the high-precision bounding box of the arc.
289          *
290          * @param x,&nbsp;y The coordinates of the upper left corner
291          * of the arc.
292          * @param w The overall width of the full ellipse of which
293          * this arc is a partial section.
294          * @param h The overall height of the full ellipse of which
295          * this arc is a partial section.
296          *
297          * @return The bounding box as a <CODE>Rectangle2D</CODE> object.
298          */

299     protected Rectangle2D JavaDoc makeBounds(double x, double y,
300                      double w, double h) {
301         return new Rectangle2D.Float JavaDoc((float) x, (float) y,
302                      (float) w, (float) h);
303     }
304     }
305
306     /**
307      * This class defines an arc specified in double precision.
308      */

309     public static class Double extends Arc2D JavaDoc {
310         /**
311          * The x coordinate of the upper left corner of the arc.
312          */

313     public double x;
314
315         /**
316          * The y coordinate of the upper left corner of the arc.
317          */

318     public double y;
319
320         /**
321          * The overall width of the full ellipse (not considering the
322          * angular extents).
323          */

324     public double width;
325
326         /**
327          * The overall height of the full ellipse (not considering the
328          * angular extents).
329          */

330     public double height;
331
332         /**
333          * The starting angle of the arc in degrees.
334          */

335     public double start;
336
337         /**
338          * The angular extent of the arc in degrees.
339          */

340     public double extent;
341
342         /**
343          * Constructs a new OPEN arc, initialized to location (0, 0),
344          * size (0, 0), angular extents (start = 0, extent = 0).
345          */

346     public Double() {
347         super(OPEN);
348     }
349
350         /**
351          * Constructs a new arc, initialized to location (0, 0),
352          * size (0, 0), angular extents (start = 0, extent = 0), and
353          * the specified closure type.
354          *
355          * @param type The closure type for the arc:
356          * {@link #OPEN OPEN}, {@link #CHORD CHORD}, or {@link #PIE PIE}.
357          */

358     public Double(int type) {
359         super(type);
360     }
361
362         /**
363          * Constructs a new arc, initialized to the specified location,
364          * size, angular extents, and closure type.
365          *
366          * @param x,&nbsp;y The coordinates of the upper left corner
367          * of the arc. (Specified in double precision.)
368          * @param w The overall width of the full ellipse of which this
369          * arc is a partial section. (Specified in double precision.)
370          * @param h The overall height of the full ellipse of which this
371          * arc is a partial section. (Specified in double precision.)
372          * @param start The starting angle of the arc in degrees.
373          * (Specified in double precision.)
374          * @param extent The angular extent of the arc in degrees.
375          * (Specified in double precision.)
376          * @param type The closure type for the arc:
377          * {@link #OPEN OPEN}, {@link #CHORD CHORD}, or {@link #PIE PIE}.
378          */

379     public Double(double x, double y, double w, double h,
380               double start, double extent, int type) {
381         super(type);
382         this.x = x;
383         this.y = y;
384         this.width = w;
385         this.height = h;
386         this.start = start;
387         this.extent = extent;
388     }
389
390         /**
391          * Constructs a new arc, initialized to the specified location,
392          * size, angular extents, and closure type.
393          *
394          * @param ellipseBounds The bounding rectangle that defines the
395          * outer boundary of the full ellipse of which this arc is a
396          * partial section.
397          * @param start The starting angle of the arc in degrees.
398          * (Specified in double precision.)
399          * @param extent The angular extent of the arc in degrees.
400          * (Specified in double precision.)
401          * @param type The closure type for the arc:
402          * {@link #OPEN OPEN}, {@link #CHORD CHORD}, or {@link #PIE PIE}.
403          */

404     public Double(Rectangle2D JavaDoc ellipseBounds,
405               double start, double extent, int type) {
406         super(type);
407         this.x = ellipseBounds.getX();
408         this.y = ellipseBounds.getY();
409         this.width = ellipseBounds.getWidth();
410         this.height = ellipseBounds.getHeight();
411         this.start = start;
412         this.extent = extent;
413     }
414
415         /**
416          * Returns the x coordinate of the upper left corner of the arc.
417          *
418          * @return The x coordinate of arc's upper left coordinate in
419          * double precision.
420          */

421     public double getX() {
422         return x;
423     }
424
425         /**
426          * Returns the y coordinate of the upper left corner of the arc.
427          *
428          * @return The y coordinate of arc's upper left coordinate in
429          * double precision.
430          */

431     public double getY() {
432         return y;
433     }
434
435         /**
436          * Returns the width of the ellipse of which this arc is
437          * a partial section.
438          *
439          * @return A double value that represents the width of the full
440          * ellipse of which this arc is a partial section.
441          */

442     public double getWidth() {
443         return width;
444     }
445
446         /**
447          * Returns the height of the ellipse of which this arc is
448          * a partial section.
449          *
450          * @return A double value that represents the height of the full
451          * ellipse of which this arc is a partial section.
452          */

453     public double getHeight() {
454         return height;
455     }
456
457         /**
458          * Returns the starting angle of the arc.
459          *
460          * @return a double value that represents the starting angle
461          * of the arc in degrees.
462      * @see #setAngleStart
463          */

464     public double getAngleStart() {
465         return start;
466     }
467
468         /**
469          * Returns the angular extent of the arc.
470          *
471          * @return A double value that represents the angular extent of
472          * the arc in degrees.
473      * @see #setAngleExtent
474          */

475     public double getAngleExtent() {
476         return extent;
477     }
478
479         /**
480          * Determines whether the arc is empty.
481          *
482          * @return <CODE>true</CODE> if the arc is empty, <CODE>false</CODE>
483          * if it not.
484          */

485     public boolean isEmpty() {
486         return (width <= 0.0 || height <= 0.0);
487     }
488
489         /**
490          * Sets the location, size, angular extents, and closure type of
491          * this arc to the specified double values.
492          *
493          * @param x,&nbsp;y The coordinates of the upper left corner
494          * of the arc.
495          * @param w The overall width of the full ellipse of which
496          * this arc is a partial section.
497          * @param h The overall height of the full ellipse of which
498          * this arc is a partial section.
499          * @param angSt The starting angle of the arc in degrees.
500          * @param angExt The angular extent of the arc in degrees.
501          * @param closure The closure type for the arc:
502          * {@link #OPEN OPEN}, {@link #CHORD CHORD}, or {@link #PIE PIE}.
503          */

504     public void setArc(double x, double y, double w, double h,
505                double angSt, double angExt, int closure) {
506         this.setArcType(closure);
507         this.x = x;
508         this.y = y;
509         this.width = w;
510         this.height = h;
511         this.start = angSt;
512         this.extent = angExt;
513     }
514
515         /**
516          * Sets the starting angle of this arc to the specified double
517          * value.
518          *
519          * @param angSt The starting angle of the arc in degrees.
520      * @see #getAngleStart
521          */

522     public void setAngleStart(double angSt) {
523         this.start = angSt;
524     }
525
526         /**
527          * Sets the angular extent of this arc to the specified double
528          * value.
529          *
530          * @param angExt The angular extent of the arc in degrees.
531      * @see #getAngleExtent
532          */

533     public void setAngleExtent(double angExt) {
534         this.extent = angExt;
535     }
536
537         /**
538          * Returns the high-precision bounding box of the arc.
539          *
540          * @param x,&nbsp;y The coordinates of the upper left corner
541          * of the arc.
542          * @param w The overall width of the full ellipse of which
543          * this arc is a partial section.
544          * @param h The overall height of the full ellipse of which
545          * this arc is a partial section.
546          *
547          * @return The bounding box as a <CODE>Rectangle2D</CODE> object.
548          */

549     protected Rectangle2D JavaDoc makeBounds(double x, double y,
550                      double w, double h) {
551         return new Rectangle2D.Double JavaDoc(x, y, w, h);
552     }
553     }
554
555     private int type;
556
557     /**
558      * This is an abstract class that cannot be instantiated directly.
559      * Type-specific implementation subclasses are available for
560      * instantiation and provide a number of formats for storing
561      * the information necessary to satisfy the various accessor
562      * methods below.
563      *
564      * @param type The closure type of this arc:
565      * {@link #OPEN OPEN}, {@link #CHORD CHORD}, or {@link #PIE PIE}.
566      * @see java.awt.geom.Arc2D.Float
567      * @see java.awt.geom.Arc2D.Double
568      */

569     protected Arc2D(int type) {
570     setArcType(type);
571     }
572
573     /**
574      * Returns the starting angle of the arc.
575      *
576      * @return A double value that represents the starting angle
577      * of the arc in degrees.
578      * @see #setAngleStart
579      */

580     public abstract double getAngleStart();
581
582     /**
583      * Returns the angular extent of the arc.
584      *
585      * @return A double value that represents the angular extent
586      * of the arc in degrees.
587      * @see #setAngleExtent
588      */

589     public abstract double getAngleExtent();
590
591     /**
592      * Returns the arc closure type of the arc: {@link #OPEN OPEN},
593      * {@link #CHORD CHORD}, or {@link #PIE PIE}.
594      * @return One of the integer constant closure types defined
595      * in this class.
596      * @see #setArcType
597      */

598     public int getArcType() {
599     return type;
600     }
601
602     /**
603      * Returns the starting point of the arc. This point is the
604      * intersection of the ray from the center defined by the
605      * starting angle and the elliptical boundary of the arc.
606      *
607      * @return A <CODE>Point2D</CODE> object representing the
608      * x,y coordinates of the starting point of the arc.
609      */

610     public Point2D JavaDoc getStartPoint() {
611     double angle = Math.toRadians(-getAngleStart());
612     double x = getX() + (Math.cos(angle) * 0.5 + 0.5) * getWidth();
613     double y = getY() + (Math.sin(angle) * 0.5 + 0.5) * getHeight();
614     return new Point2D.Double JavaDoc(x, y);
615     }
616
617     /**
618      * Returns the ending point of the arc. This point is the
619      * intersection of the ray from the center defined by the
620      * starting angle plus the angular extent of the arc and the
621      * elliptical boundary of the arc.
622      *
623      * @return A <CODE>Point2D</CODE> object representing the
624      * x,y coordinates of the ending point of the arc.
625      */

626     public Point2D JavaDoc getEndPoint() {
627     double angle = Math.toRadians(-getAngleStart() - getAngleExtent());
628     double x = getX() + (Math.cos(angle) * 0.5 + 0.5) * getWidth();
629     double y = getY() + (Math.sin(angle) * 0.5 + 0.5) * getHeight();
630     return new Point2D.Double JavaDoc(x, y);
631     }
632
633     /**
634      * Sets the location, size, angular extents, and closure type of
635      * this arc to the specified double values.
636      *
637      * @param x,&nbsp;y The coordinates of the upper left corner of
638      * the arc.
639      * @param w The overall width of the full ellipse of which
640      * this arc is a partial section.
641      * @param h The overall height of the full ellipse of which
642      * this arc is a partial section.
643      * @param angSt The starting angle of the arc in degrees.
644      * @param angExt The angular extent of the arc in degrees.
645      * @param closure The closure type for the arc:
646      * {@link #OPEN OPEN}, {@link #CHORD CHORD}, or {@link #PIE PIE}.
647      */

648     public abstract void setArc(double x, double y, double w, double h,
649                 double angSt, double angExt, int closure);
650
651     /**
652      * Sets the location, size, angular extents, and closure type of
653      * this arc to the specified values.
654      *
655      * @param loc The <CODE>Point2D</CODE> representing the coordinates of
656      * the upper left corner of the arc.
657      * @param size The <CODE>Dimension2D</CODE> representing the width
658      * and height of the full ellipse of which this arc is
659      * a partial section.
660      * @param angSt The starting angle of the arc in degrees.
661      * (Specified in double precision.)
662      * @param angExt The angular extent of the arc in degrees.
663      * (Specified in double precision.)
664      * @param closure The closure type for the arc:
665      * {@link #OPEN OPEN}, {@link #CHORD CHORD}, or {@link #PIE PIE}.
666      */

667     public void setArc(Point2D JavaDoc loc, Dimension2D JavaDoc size,
668                double angSt, double angExt, int closure) {
669     setArc(loc.getX(), loc.getY(), size.getWidth(), size.getHeight(),
670            angSt, angExt, closure);
671     }
672
673     /**
674      * Sets the location, size, angular extents, and closure type of
675      * this arc to the specified values.
676      *
677      * @param rect The bounding rectangle that defines the
678      * outer boundary of the full ellipse of which this arc is a
679      * partial section.
680      * @param angSt The starting angle of the arc in degrees.
681      * (Specified in double precision.)
682      * @param angExt The angular extent of the arc in degrees.
683      * (Specified in double precision.)
684      * @param closure The closure type for the arc:
685      * {@link #OPEN OPEN}, {@link #CHORD CHORD}, or {@link #PIE PIE}.
686      */

687     public void setArc(Rectangle2D JavaDoc rect, double angSt, double angExt,
688                int closure) {
689     setArc(rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight(),
690            angSt, angExt, closure);
691     }
692
693     /**
694      * Sets this arc to be the same as the specified arc.
695      *
696      * @param a The <CODE>Arc2D</CODE> to use to set the arc's values.
697      */

698     public void setArc(Arc2D JavaDoc a) {
699     setArc(a.getX(), a.getY(), a.getWidth(), a.getHeight(),
700            a.getAngleStart(), a.getAngleExtent(), a.type);
701     }
702
703     /**
704      * Sets the position, bounds, angular extents, and closure type of
705      * this arc to the specified values. The arc is defined by a center
706      * point and a radius rather than a bounding box for the full ellipse.
707      *
708      * @param x,&nbsp;y The coordinates of the center of the arc.
709      * (Specified in double precision.)
710      * @param radius The radius of the arc. (Specified in double precision.)
711      * @param angSt The starting angle of the arc in degrees.
712      * (Specified in double precision.)
713      * @param angExt The angular extent of the arc in degrees.
714      * (Specified in double precision.)
715      * @param closure The closure type for the arc:
716      * {@link #OPEN OPEN}, {@link #CHORD CHORD}, or {@link #PIE PIE}.
717      */

718     public void setArcByCenter(double x, double y, double radius,
719                    double angSt, double angExt, int closure) {
720     setArc(x - radius, y - radius, radius * 2.0, radius * 2.0,
721            angSt, angExt, closure);
722     }
723
724     /**
725      * Sets the position, bounds, and angular extents of this arc to the
726      * specified value. The starting angle of the arc is tangent to the
727      * line specified by points (p1, p2), the ending angle is tangent to
728      * the line specified by points (p2, p3), and the arc has the
729      * specified radius.
730      *
731      * @param p1 The first point that defines the arc. The starting
732      * angle of the arc is tangent to the line specified by points (p1, p2).
733      * @param p2 The second point that defines the arc. The starting
734      * angle of the arc is tangent to the line specified by points (p1, p2).
735      * The ending angle of the arc is tangent to the line specified by
736      * points (p2, p3).
737      * @param p3 The third point that defines the arc. The ending angle
738      * of the arc is tangent to the line specified by points (p2, p3).
739      * @param radius The radius of the arc. (Specified in double precision.)
740      */

741     public void setArcByTangent(Point2D JavaDoc p1, Point2D JavaDoc p2, Point2D JavaDoc p3,
742                 double radius) {
743     double ang1 = Math.atan2(p1.getY() - p2.getY(),
744                  p1.getX() - p2.getX());
745     double ang2 = Math.atan2(p3.getY() - p2.getY(),
746                  p3.getX() - p2.getX());
747     double diff = ang2 - ang1;
748     if (diff > Math.PI) {
749         ang2 -= Math.PI * 2.0;
750     } else if (diff < -Math.PI) {
751         ang2 += Math.PI * 2.0;
752     }
753     double bisect = (ang1 + ang2) / 2.0;
754     double theta = Math.abs(ang2 - bisect);
755     double dist = radius / Math.sin(theta);
756     double x = p2.getX() + dist * Math.cos(bisect);
757     double y = p2.getY() + dist * Math.sin(bisect);
758     // REMIND: This needs some work...
759
if (ang1 < ang2) {
760         ang1 -= Math.PI / 2.0;
761         ang2 += Math.PI / 2.0;
762     } else {
763         ang1 += Math.PI / 2.0;
764         ang2 -= Math.PI / 2.0;
765     }
766     ang1 = Math.toDegrees(-ang1);
767     ang2 = Math.toDegrees(-ang2);
768     diff = ang2 - ang1;
769     if (diff < 0) {
770         diff += 360;
771     } else {
772         diff -= 360;
773     }
774     setArcByCenter(x, y, radius, ang1, diff, type);
775     }
776
777     /**
778      * Sets the starting angle of this arc to the specified double
779      * value.
780      *
781      * @param angSt The starting angle of the arc in degrees.
782      * @see #getAngleStart
783      */

784     public abstract void setAngleStart(double angSt);
785
786     /**
787      * Sets the angular extent of this arc to the specified double
788      * value.
789      *
790      * @param angExt The angular extent of the arc in degrees.
791      * @see #getAngleExtent
792      */

793     public abstract void setAngleExtent(double angExt);
794
795     /**
796      * Sets the starting angle of this arc to the angle that the
797      * specified point defines relative to the center of this arc.
798      * The angular extent of the arc will remain the same.
799      *
800      * @param p The <CODE>Point2D</CODE> that defines the starting angle.
801      * @see #getAngleStart
802      */

803     public void setAngleStart(Point2D JavaDoc p) {
804     // Bias the dx and dy by the height and width of the oval.
805
double dx = getHeight() * (p.getX() - getCenterX());
806     double dy = getWidth() * (p.getY() - getCenterY());
807     setAngleStart(-Math.toDegrees(Math.atan2(dy, dx)));
808     }
809
810     /**
811      * Sets the starting angle and angular extent of this arc using two
812      * sets of coordinates. The first set of coordinates is used to
813      * determine the angle of the starting point relative to the arc's
814      * center. The second set of coordinates is used to determine the
815      * angle of the end point relative to the arc's center.
816      * The arc will always be non-empty and extend counterclockwise
817      * from the first point around to the second point.
818      *
819      * @param x1,&nbsp;y1 The coordinates of the arc's starting point.
820      * @param x2,&nbsp;y2 The coordinates of the arc's ending point.
821      */

822     public void setAngles(double x1, double y1, double x2, double y2) {
823     double x = getCenterX();
824     double y = getCenterY();
825     double w = getWidth();
826     double h = getHeight();
827     // Note: reversing the Y equations negates the angle to adjust
828
// for the upside down coordinate system.
829
// Also we should bias atans by the height and width of the oval.
830
double ang1 = Math.atan2(w * (y - y1), h * (x1 - x));
831     double ang2 = Math.atan2(w * (y - y2), h * (x2 - x));
832     ang2 -= ang1;
833     if (ang2 <= 0.0) {
834         ang2 += Math.PI * 2.0;
835     }
836     setAngleStart(Math.toDegrees(ang1));
837     setAngleExtent(Math.toDegrees(ang2));
838     }
839
840     /**
841      * Sets the starting angle and angular extent of this arc using
842      * two points. The first point is used to determine the angle of
843      * the starting point relative to the arc's center.
844      * The second point is used to determine the angle of the end point
845      * relative to the arc's center.
846      * The arc will always be non-empty and extend counterclockwise
847      * from the first point around to the second point.
848      *
849      * @param p1 The <CODE>Point2D</CODE> that defines the arc's
850      * starting point.
851      * @param p2 The <CODE>Point2D</CODE> that defines the arc's
852      * ending point.
853      */

854     public void setAngles(Point2D JavaDoc p1, Point2D JavaDoc p2) {
855     setAngles(p1.getX(), p1.getY(), p2.getX(), p2.getY());
856     }
857
858     /**
859      * Sets the closure type of this arc to the specified value:
860      * <CODE>OPEN</CODE>, <CODE>CHORD</CODE>, or <CODE>PIE</CODE>.
861      *
862      * @param type The integer constant that represents the closure
863      * type of this arc: {@link #OPEN}, {@link #CHORD}, or
864      * {@link #PIE}.
865      *
866      * @throws IllegalArgumentException if <code>type</code> is not
867      * 0, 1, or 2.+
868      * @see #getArcType
869      */

870     public void setArcType(int type) {
871     if (type < OPEN || type > PIE) {
872         throw new IllegalArgumentException JavaDoc("invalid type for Arc: "+type);
873     }
874     this.type = type;
875     }
876
877     /**
878      * Sets the location and size of the outer bounds of this arc
879      * to the specified values.
880      *
881      * @param x,&nbsp;y The coordinates of the upper left corner of the
882      * arc's bounding box. (Specified in double precision.)
883      * @param w The width of the arc's bounding box. (Specified in
884      * double precision.)
885      * @param h The height of the arc's bounding box. (Specified in
886      * double precision.)
887      */

888     public void setFrame(double x, double y, double w, double h) {
889     setArc(x, y, w, h, getAngleStart(), getAngleExtent(), type);
890     }
891
892     /**
893      * Returns the high-precision bounding box of the arc. The bounding
894      * box contains only the part of this <code>Arc2D</code> that is
895      * in between the starting and ending angles and contains the pie
896      * wedge, if this <code>Arc2D</code> has a <code>PIE</code> closure type.
897      * <p>
898      * This method differs from the
899      * {@link RectangularShape#getBounds() getBounds} in that the
900      * <code>getBounds</code> method only returns the bounds of the
901      * enclosing ellipse of this <code>Arc2D</code> without considering
902      * the starting and ending angles of this <code>Arc2D</code>.
903      *
904      * @return the <CODE>Rectangle2D</CODE> that represents the arc's
905      * bounding box.
906      */

907     public Rectangle2D JavaDoc getBounds2D() {
908     if (isEmpty()) {
909         return makeBounds(getX(), getY(), getWidth(), getHeight());
910     }
911     double x1, y1, x2, y2;
912     if (getArcType() == PIE) {
913         x1 = y1 = x2 = y2 = 0.0;
914     } else {
915         x1 = y1 = 1.0;
916         x2 = y2 = -1.0;
917     }
918     double angle = 0.0;
919     for (int i = 0; i < 6; i++) {
920         if (i < 4) {
921         // 0-3 are the four quadrants
922
angle += 90.0;
923         if (!containsAngle(angle)) {
924             continue;
925         }
926         } else if (i == 4) {
927         // 4 is start angle
928
angle = getAngleStart();
929         } else {
930         // 5 is end angle
931
angle += getAngleExtent();
932         }
933         double rads = Math.toRadians(-angle);
934         double xe = Math.cos(rads);
935         double ye = Math.sin(rads);
936         x1 = Math.min(x1, xe);
937         y1 = Math.min(y1, ye);
938         x2 = Math.max(x2, xe);
939         y2 = Math.max(y2, ye);
940     }
941     double w = getWidth();
942     double h = getHeight();
943     x2 = (x2 - x1) * 0.5 * w;
944     y2 = (y2 - y1) * 0.5 * h;
945     x1 = getX() + (x1 * 0.5 + 0.5) * w;
946     y1 = getY() + (y1 * 0.5 + 0.5) * h;
947     return makeBounds(x1, y1, x2, y2);
948     }
949
950     /**
951      * Constructs a <code>Rectangle2D</code> of the appropriate precision
952      * to hold the parameters calculated to be the bounding box
953      * of this arc.
954      *
955      * @param x,&nbsp;y The coordinates of the upper left corner of the
956      * bounding box. (Specified in double precision.)
957      * @param w The width of the bounding box. (Specified in
958      * double precision.)
959      * @param h The height of the bounding box. (Specified in
960      * double precision.)
961      * @return a <code>Rectangle2D</code> that is the bounding box
962      * of this arc.
963      */

964     protected abstract Rectangle2D JavaDoc makeBounds(double x, double y,
965                           double w, double h);
966
967     /*
968      * Normalizes the specified angle into the range -180 to 180.
969      */

970     static double normalizeDegrees(double angle) {
971     if (angle > 180.0) {
972         if (angle <= (180.0 + 360.0)) {
973         angle = angle - 360.0;
974         } else {
975         angle = Math.IEEEremainder(angle, 360.0);
976         // IEEEremainder can return -180 here for some input values...
977
if (angle == -180.0) {
978             angle = 180.0;
979         }
980         }
981