KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  * @(#)RoundRectangle2D.java 1.18 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  * The <code>RoundRectangle2D</code> class defines a rectangle with
12  * rounded corners defined by a location (x,&nbsp;y), a
13  * dimension (w&nbsp;x&nbsp;h), and the width and height of an arc
14  * with which to round the corners.
15  * <p>
16  * This class is the abstract superclass for all objects that
17  * store a 2D rounded rectangle.
18  * The actual storage representation of the coordinates is left to
19  * the subclass.
20  *
21  * @version 1.18, 12/19/03
22  * @author Jim Graham
23  */

24 public abstract class RoundRectangle2D extends RectangularShape JavaDoc {
25     /**
26      * The <code>Float</code> class defines a rectangle with rounded
27      * corners all specified in <code>float</code> coordinates.
28      */

29     public static class Float extends RoundRectangle2D JavaDoc {
30     /**
31      * The X coordinate of this <code>RoundRectangle2D</code>.
32      */

33     public float x;
34
35     /**
36          * The Y coordinate of this <code>RoundRectangle2D</code>.
37      */

38     public float y;
39
40     /**
41          * The width of this <code>RoundRectangle2D</code>.
42      */

43     public float width;
44
45     /**
46          * The height of this <code>RoundRectangle2D</code>.
47      */

48     public float height;
49
50     /**
51      * The width of the arc that rounds off the corners.
52      */

53     public float arcwidth;
54
55     /**
56      * The height of the arc that rounds off the corners.
57      */

58     public float archeight;
59
60     /**
61      * Constructs a new <code>RoundRectangle2D</code>, initialized to
62          * location (0.0,&nbsp;0), size (0.0,&nbsp;0.0), and corner arcs
63          * of radius 0.0.
64      */

65     public Float() {
66     }
67
68     /**
69      * Constructs and initializes a <code>RoundRectangle2D</code>
70          * from the specified coordinates.
71      * @param x,&nbsp;y the coordinates to which to set the newly
72          * constructed <code>RoundRectangle2D</code>
73      * @param w the width to which to set the newly
74          * constructed <code>RoundRectangle2D</code>
75      * @param h the height to which to set the newly
76          * constructed <code>RoundRectangle2D</code>
77          * @param arcw the width of the arc to use to round off the
78          * corners of the newly constructed <code>RoundRectangle2D</code>
79          * @param arch the height of the arc to use to round off the
80          * corners of the newly constructed <code>RoundRectangle2D</code>
81      */

82     public Float(float x, float y, float w, float h,
83                    float arcw, float arch) {
84         setRoundRect(x, y, w, h, arcw, arch);
85     }
86
87     /**
88      * Returns the X coordinate of this <code>RoundRectangle2D</code>
89          * in <code>double</code> precision.
90          * @return the X coordinate of this <code>RoundRectangle2D</code>.
91      */

92     public double getX() {
93         return (double) x;
94     }
95
96     /**
97      * Returns the Y coordinate of this <code>RoundRectangle2D</code>
98          * in <code>double</code> precision.
99          * @return the Y coordinate of this <code>RoundRectangle2D</code>.
100          */

101     public double getY() {
102         return (double) y;
103     }
104
105     /**
106      * Returns the width of this <code>RoundRectangle2D</code>
107          * in <code>double</code> precision.
108          * @return the width of this <code>RoundRectangle2D</code>.
109          */

110     public double getWidth() {
111         return (double) width;
112     }
113
114     /**
115          * Returns the height of this <code>RoundRectangle2D</code>
116          * in <code>double</code> precision.
117          * @return the height of this <code>RoundRectangle2D</code>.
118          */

119     public double getHeight() {
120         return (double) height;
121     }
122
123     /**
124      * Returns the width of the arc that rounds off the corners.
125          * @return the width of the arc that rounds off the corners
126          * of this <code>RoundRectangle2D</code>.
127      */

128     public double getArcWidth() {
129         return (double) arcwidth;
130     }
131
132     /**
133          * Returns the height of the arc that rounds off the corners.
134          * @return the height of the arc that rounds off the corners
135          * of this <code>RoundRectangle2D</code>.
136          */

137     public double getArcHeight() {
138         return (double) archeight;
139     }
140
141     /**
142      * Determines whether or not this <code>RoundRectangle2D</code>
143          * is empty.
144          * @return <code>true</code> if this <code>RoundRectangle2D</code>
145          * is empty; <code>false</code> othwerwise.
146      */

147     public boolean isEmpty() {
148         return (width <= 0.0f) || (height <= 0.0f);
149     }
150
151     /**
152      * Sets the location, size, and arc radii of this
153          * <code>RoundRectangle2D</code> to the
154      * specified <code>float</code> values.
155          * @param x,&nbsp;y the coordinates to which to set the
156          * location of this <code>RoundRectangle2D</code>
157          * @param w the width to which to set this
158          * <code>RoundRectangle2D</code>
159          * @param h the height to which to set this
160          * <code>RoundRectangle2D</code>
161          * @param arcw the width to which to set the arc of this
162          * <code>RoundRectangle2D</code>
163          * @param arch the height to which to set the arc of this
164          * <code>RoundRectangle2D</code>
165      */

166     public void setRoundRect(float x, float y, float w, float h,
167                  float arcw, float arch) {
168         this.x = x;
169         this.y = y;
170         this.width = w;
171         this.height = h;
172         this.arcwidth = arcw;
173         this.archeight = arch;
174     }
175
176     /**
177      * Sets the location, size, and arc radii of this
178          * <code>RoundRectangle2D</code> to the
179      * specified <code>double</code> values.
180          * @param x,&nbsp;y the coordinates to which to set the
181          * location of this <code>RoundRectangle2D</code>
182          * @param w the width to which to set this
183          * <code>RoundRectangle2D</code>
184          * @param h the height to which to set this
185          * <code>RoundRectangle2D</code>
186          * @param arcw the width to which to set the arc of this
187          * <code>RoundRectangle2D</code>
188          * @param arch the height to which to set the arc of this
189          * <code>RoundRectangle2D</code>
190          */

191     public void setRoundRect(double x, double y, double w, double h,
192                  double arcw, double arch) {
193         this.x = (float) x;
194         this.y = (float) y;
195         this.width = (float) w;
196         this.height = (float) h;
197         this.arcwidth = (float) arcw;
198         this.archeight = (float) arch;
199     }
200
201     /**
202      * Sets this <code>RoundRectangle2D</code> to be the same as the
203          * specified <code>RoundRectangle2D</code>.
204          * @param rr the specified <code>RoundRectangle2D</code>
205      */

206     public void setRoundRect(RoundRectangle2D JavaDoc rr) {
207         this.x = (float) rr.getX();
208         this.y = (float) rr.getY();
209         this.width = (float) rr.getWidth();
210         this.height = (float) rr.getHeight();
211         this.arcwidth = (float) rr.getArcWidth();
212         this.archeight = (float) rr.getArcHeight();
213     }
214
215     /**
216      * Returns the high precision bounding box of this
217          * <code>RoundRectangle2D</code>.
218          * @return a {@link Rectangle2D} that is the bounding
219          * box of this <code>RoundRectangle2D</code>.
220      */

221     public Rectangle2D JavaDoc getBounds2D() {
222         return new Rectangle2D.Float JavaDoc(x, y, width, height);
223     }
224     }
225
226     /**
227      * The <code>Double</code> class defines a rectangle with rounded
228      * corners all specified in <code>double</code> coordinates.
229      */

230     public static class Double extends RoundRectangle2D JavaDoc {
231     /**
232          * The X coordinate of this <code>RoundRectangle2D</code>.
233          */

234     public double x;
235
236     /**
237          * The Y coordinate of this <code>RoundRectangle2D</code>.
238          */

239     public double y;
240
241     /**
242          * The width of this <code>RoundRectangle2D</code>.
243      */

244     public double width;
245
246     /**
247          * The height of this <code>RoundRectangle2D</code>.
248      */

249     public double height;
250
251     /**
252          * The width of the arc that rounds off the corners.
253      */

254     public double arcwidth;
255
256     /**
257          * The height of the arc that rounds off the corners.
258      */

259     public double archeight;
260
261     /**
262          * Constructs a new <code>RoundRectangle2D</code>, initialized to
263          * location (0.0,&nbsp;0), size (0.0,&nbsp;0.0), and corner arcs
264          * of radius 0.0.
265          */

266     public Double() {
267     }
268
269     /**
270          * Constructs and initializes a <code>RoundRectangle2D</code>
271          * from the specified coordinates.
272          * @param x,&nbsp;y the coordinates to which to set the newly
273          * constructed <code>RoundRectangle2D</code>
274          * @param w the width to which to set the newly
275          * constructed <code>RoundRectangle2D</code>
276          * @param h the height to which to set the newly
277          * constructed <code>RoundRectangle2D</code>
278          * @param arcw the width of the arc to use to round off the
279          * corners of the newly constructed <code>RoundRectangle2D</code>
280          * @param arch the height of the arc to use to round off the
281          * corners of the newly constructed <code>RoundRectangle2D</code>
282          */

283     public Double(double x, double y, double w, double h,
284               double arcw, double arch) {
285         setRoundRect(x, y, w, h, arcw, arch);
286     }
287
288     /**
289          * Returns the X coordinate of this <code>RoundRectangle2D</code>
290          * in <code>double</code> precision.
291          * @return the X coordinate of this <code>RoundRectangle2D</code>.
292          */

293     public double getX() {
294         return x;
295     }
296
297     /**
298          * Returns the Y coordinate of this <code>RoundRectangle2D</code>
299          * in <code>double</code> precision.
300          * @return the Y coordinate of this <code>RoundRectangle2D</code>.
301          */

302     public double getY() {
303         return y;
304     }
305
306     /**
307          * Returns the width of this <code>RoundRectangle2D</code>
308          * in <code>double</code> precision.
309          * @return the width of this <code>RoundRectangle2D</code>.
310          */

311     public double getWidth() {
312         return width;
313     }
314
315     /**
316          * Returns the height of this <code>RoundRectangle2D</code>
317          * in <code>double</code> precision.
318          * @return the height of this <code>RoundRectangle2D</code>.
319          */

320     public double getHeight() {
321         return height;
322     }
323
324     /**
325          * Returns the width of the arc that rounds off the corners.
326          * @return the width of the arc that rounds off the corners
327          * of this <code>RoundRectangle2D</code>.
328          */

329     public double getArcWidth() {
330         return arcwidth;
331     }
332
333     /**
334          * Returns the height of the arc that rounds off the corners.
335          * @return the height of the arc that rounds off the corners
336          * of this <code>RoundRectangle2D</code>.
337          */

338     public double getArcHeight() {
339         return archeight;
340     }
341
342     /**
343          * Determines whether or not this <code>RoundRectangle2D</code>
344          * is empty.
345          * @return <code>true</code> if this <code>RoundRectangle2D</code>
346          * is empty; <code>false</code> othwerwise.
347          */

348     public boolean isEmpty() {
349         return (width <= 0.0f) || (height <= 0.0f);
350     }
351
352     /**
353          * Sets the location, size, and arc radii of this
354          * <code>RoundRectangle2D</code> to the
355          * specified <code>double</code> values.
356          * @param x,&nbsp;y the coordinates to which to set the
357          * location of this <code>RoundRectangle2D</code>
358          * @param w the width to which to set this
359          * <code>RoundRectangle2D</code>
360          * @param h the height to which to set this
361          * <code>RoundRectangle2D</code>
362          * @param arcw the width to which to set the arc of this
363          * <code>RoundRectangle2D</code>
364          * @param arch the height to which to set the arc of this
365          * <code>RoundRectangle2D</code>
366          */

367     public void setRoundRect(double x, double y, double w, double h,
368                  double arcw, double arch) {
369         this.x = x;
370         this.y = y;
371         this.width = w;
372         this.height = h;
373         this.arcwidth = arcw;
374         this.archeight = arch;
375     }
376
377     /**
378          * Sets this <code>RoundRectangle2D</code> to be the same as the
379          * specified <code>RoundRectangle2D</code>.
380          * @param rr the specified <code>RoundRectangle2D</code>
381          */

382     public void setRoundRect(RoundRectangle2D JavaDoc rr) {
383         this.x = rr.getX();
384         this.y = rr.getY();
385         this.width = rr.getWidth();
386         this.height = rr.getHeight();
387         this.arcwidth = rr.getArcWidth();
388         this.archeight = rr.getArcHeight();
389     }
390
391     /**
392          * Returns the high precision bounding box of this
393          * <code>RoundRectangle2D</code>.
394          * @return a {@link Rectangle2D} that is the bounding
395          * box of this <code>RoundRectangle2D</code>.
396      */

397     public Rectangle2D JavaDoc getBounds2D() {
398         return new Rectangle2D.Double JavaDoc(x, y, width, height);
399     }
400     }
401
402     /**
403      * This is an abstract class that cannot be instantiated directly.
404      * Type-specific implementation subclasses are available for
405      * instantiation and provide a number of formats for storing
406      * the information necessary to satisfy the various accessor
407      * methods below.
408      *
409      * @see java.awt.geom.RoundRectangle2D.Float
410      * @see java.awt.geom.RoundRectangle2D.Double
411      */

412     protected RoundRectangle2D() {
413     }
414
415     /**
416      * Gets the width of the arc that rounds off the corners.
417      * @return the width of the arc that rounds off the corners
418      * of this <code>RoundRectangle2D</code>.
419      */

420     public abstract double getArcWidth();
421
422     /**
423      * Gets the height of the arc that rounds off the corners.
424      * @return the height of the arc that rounds off the corners
425      * of this <code>RoundRectangle2D</code>.
426      */

427     public abstract double getArcHeight();
428
429     /**
430      * Sets the location, size, and corner radii of this
431      * <code>RoundRectangle2D</code> to the specified
432      * <code>double</code> values.
433      * @param x,&nbsp;y the coordinates to which to set the
434      * location of this <code>RoundRectangle2D</code>
435      * @param w the width to which to set this
436      * <code>RoundRectangle2D</code>
437      * @param h the height to which to set this
438      * <code>RoundRectangle2D</code>
439      * @param arcWidth the width to which to set the arc of this
440      * <code>RoundRectangle2D</code>
441      * @param arcHeight the height to which to set the arc of this
442      * <code>RoundRectangle2D</code>
443      */

444     public abstract void setRoundRect(double x, double y, double w, double h,
445                       double arcWidth, double arcHeight);
446
447     /**
448      * Sets this <code>RoundRectangle2D</code> to be the same as the
449      * specified <code>RoundRectangle2D</code>.
450      * @param rr the specified <code>RoundRectangle2D</code>
451      */

452     public void setRoundRect(RoundRectangle2D JavaDoc rr) {
453     setRoundRect(rr.getX(), rr.getY(), rr.getWidth(), rr.getHeight(),
454              rr.getArcWidth(), rr.getArcHeight());
455     }
456
457     /**
458      * Sets the location and size of the outer bounds of this
459      * <code>RoundRectangle2D</code> to the specified rectangular values.
460      * @param x,&nbsp;y the coordinates to which to set the location
461      * of this <code>RoundRectangle2D</code>
462      * @param w the width to which to set this
463      * <code>RoundRectangle2D</code>
464      * @param h the height to which to set this
465      * <code>RoundRectangle2D</code>
466      */

467     public void setFrame(double x, double y, double w, double h) {
468     setRoundRect(x, y, w, h, getArcWidth(), getArcHeight());
469     }
470
471     /**
472      * Tests if the specified coordinates are inside the boundary of
473      * this <code>RoundRectangle2D</code>.
474      * @param x,&nbsp;y the coordinates to test
475      * @return <code>true</code> if the specified coordinates are
476      * inside the boundary of this <code>RoundRectangle2D</code>;
477      * <code>false</code> otherwise.
478      */

479     public boolean contains(double x, double y) {
480     if (isEmpty()) {
481         return false;
482     }
483     double rrx0 = getX();
484     double rry0 = getY();
485     double rrx1 = rrx0 + getWidth();
486     double rry1 = rry0 + getHeight();
487     // Check for trivial rejection - point is outside bounding rectangle
488
if (x < rrx0 || y < rry0 || x >= rrx1 || y >= rry1) {
489         return false;
490     }
491     double aw = Math.min(getWidth(), Math.abs(getArcWidth())) / 2.0;
492     double ah = Math.min(getHeight(), Math.abs(getArcHeight())) / 2.0;
493     // Check which corner point is in and do circular containment
494
// test - otherwise simple acceptance
495
if (x >= (rrx0 += aw) && x < (rrx0 = rrx1 - aw)) {
496         return true;
497     }
498     if (y >= (rry0 += ah) && y < (rry0 = rry1 - ah)) {
499         return true;
500     }
501     x = (x - rrx0) / aw;
502     y = (y - rry0) / ah;
503     return (x * x + y * y <= 1.0);
504     }
505
506     private int classify(double coord, double left, double right,
507              double arcsize) {
508     if (coord < left) {
509         return 0;
510     } else if (coord < left + arcsize) {
511         return 1;
512     } else if (coord < right - arcsize) {
513         return 2;
514     } else if (coord < right) {
515         return 3;
516     } else {
517         return 4;
518     }
519     }
520
521     /**
522      * Tests if the interior of this <code>RoundRectangle2D</code>
523      * intersects the interior of a specified set of rectangular
524      * coordinates.
525      * @param x,&nbsp;y the coordinates of the upper left corner
526      * of the specified set of rectangular coordinates
527      * @param w the width of the specified set of rectangular
528      * coordinates
529      * @param h the height of the specified set of rectangular
530      * coordinates
531      * @return <code>true</code> if the interior of this
532      * <code>RoundRectangle2D</code> intersects the interior of the
533      * specified set of rectangular coordinates.
534      */

535     public boolean intersects(double x, double y, double w, double h) {
536     if (isEmpty() || w <= 0 || h <= 0) {
537         return false;
538     }
539     double rrx0 = getX();
540     double rry0 = getY();
541     double rrx1 = rrx0 + getWidth();
542     double rry1 = rry0 + getHeight();
543     // Check for trivial rejection - bounding rectangles do not intersect
544
if (x + w <= rrx0 || x >= rrx1 || y + h <= rry0 || y >= rry1) {
545         return false;
546     }
547     double aw = Math.min(getWidth(), Math.abs(getArcWidth())) / 2.0;
548     double ah = Math.min(getHeight(), Math.abs(getArcHeight())) / 2.0;
549     int x0class = classify(x, rrx0, rrx1, aw);
550     int x1class = classify(x + w, rrx0, rrx1, aw);
551     int y0class = classify(y, rry0, rry1, ah);
552     int y1class = classify(y + h, rry0, rry1, ah);
553     // Trivially accept if any point is inside inner rectangle
554
if (x0class == 2 || x1class == 2 || y0class == 2 || y1class == 2) {
555         return true;
556     }
557     // Trivially accept if either edge spans inner rectangle
558
if ((x0class < 2 && x1class > 2) || (y0class < 2 && y1class > 2)) {
559         return true;
560     }
561     // Since neither edge spans the center, then one of the corners
562
// must be in one of the rounded edges. We detect this case if
563
// a [xy]0class is 3 or a [xy]1class is 1. One of those two cases
564
// must be true for each direction.
565
// We now find a "nearest point" to test for being inside a rounded
566
// corner.
567
x = (x1class == 1) ? (x = x + w - (rrx0 + aw)) : (x = x - (rrx1 - aw));
568     y = (y1class == 1) ? (y = y + h - (rry0 + ah)) : (y = y - (rry1 - ah));
569     x = x / aw;
570     y = y / ah;
571     return (x * x + y * y <= 1.0);
572     }
573
574     /**
575      * Tests if the interior of this <code>RoundRectangle2D</code>
576      * entirely contains the specified set of rectangular coordinates.
577      * @param x,&nbsp;y the coordinates of the specified set of
578      * rectangular coordinates
579      * @param w the width of the specified set of rectangular
580      * coordinates
581      * @param h the height of the specified set of rectangular
582      * coordinates
583      * @return <code>true</code> if the interior of this
584      * <code>RoundRectangle2D</code> entirely contains the specified
585      * set of rectangular coordinates; <code>false</code> otherwise.
586      */

587     public boolean contains(double x, double y, double w, double h) {
588     if (isEmpty() || w <= 0 || h <= 0) {
589         return false;
590     }
591     return (contains(x, y) &&
592         contains(x + w, y) &&
593         contains(x, y + h) &&
594         contains(x + w, y + h));
595     }
596
597     /**
598      * Returns an iteration object that defines the boundary of this
599      * <code>RoundRectangle2D</code>.
600      * The iterator for this class is multi-threaded safe, which means
601      * that this <code>RoundRectangle2D</code> class guarantees that
602      * modifications to the geometry of this <code>RoundRectangle2D</code>
603      * object do not affect any iterations of that geometry that
604      * are already in process.
605      * @param at an optional <code>AffineTransform</code> to be applied to
606      * the coordinates as they are returned in the iteration, or
607      * <code>null</code> if untransformed coordinates are desired
608      * @return the <code>PathIterator</code> object that returns the
609      * geometry of the outline of this
610      * <code>RoundRectangle2D</code>, one segment at a time.
611      */

612     public PathIterator JavaDoc getPathIterator(AffineTransform JavaDoc at) {
613     return new RoundRectIterator JavaDoc(this, at);
614     }
615 }
616
Popular Tags