41 |
import java.util.NoSuchElementException; |
import java.util.NoSuchElementException; |
42 |
|
|
43 |
/** |
/** |
44 |
* STUBS ONLY |
* This class represents all arcs (segments of an ellipse in 2-D space). The |
45 |
* XXX Implement and document. |
* arcs are defined by starting angle and extent (arc length) in degrees, as |
46 |
|
* opposed to radians (like the rest of Java), and can be open, chorded, or |
47 |
|
* wedge shaped. The angles are skewed according to the ellipse, so that 45 |
48 |
|
* degrees always points to the upper right corner (positive x, negative y) |
49 |
|
* of the bounding rectangle. A positive extent draws a counterclockwise arc, |
50 |
|
* and while the angle can be any value, the path iterator only traverses the |
51 |
|
* first 360 degrees. Storage is up to the subclasses. |
52 |
|
* |
53 |
|
* @author Eric Blake <ebb9@email.byu.edu> |
54 |
|
* @since 1.2 |
55 |
|
* @status updated to 1.4, but still missing functionality |
56 |
*/ |
*/ |
57 |
public abstract class Arc2D extends RectangularShape |
public abstract class Arc2D extends RectangularShape |
58 |
{ |
{ |
59 |
|
/** |
60 |
|
* An open arc, with no segment connecting the endpoints. This type of |
61 |
|
* arc still contains the same points as a chorded version. |
62 |
|
*/ |
63 |
public static final int OPEN = 0; |
public static final int OPEN = 0; |
64 |
|
|
65 |
|
/** |
66 |
|
* A closed arc with a single segment connecting the endpoints (a chord). |
67 |
|
*/ |
68 |
public static final int CHORD = 1; |
public static final int CHORD = 1; |
69 |
|
|
70 |
|
/** |
71 |
|
* A closed arc with two segments, one from each endpoint, meeting at the |
72 |
|
* center of the ellipse. |
73 |
|
*/ |
74 |
public static final int PIE = 2; |
public static final int PIE = 2; |
75 |
|
|
76 |
|
/** The closure type of this arc. */ |
77 |
private int type; |
private int type; |
78 |
|
|
79 |
|
/** |
80 |
|
* Create a new arc, with the specified closure type. |
81 |
|
* |
82 |
|
* @param type one of {@link #OPEN}, {@link #CHORD}, or {@link #PIE}. |
83 |
|
* @throws IllegalArgumentException if type is invalid |
84 |
|
*/ |
85 |
protected Arc2D(int type) |
protected Arc2D(int type) |
86 |
{ |
{ |
87 |
if (type < OPEN || type > PIE) |
if (type < OPEN || type > PIE) |
89 |
this.type = type; |
this.type = type; |
90 |
} |
} |
91 |
|
|
92 |
/** Start in degrees. */ |
/** |
93 |
|
* Get the starting angle of the arc in degrees. |
94 |
|
* |
95 |
|
* @return the starting angle |
96 |
|
* @see #setAngleStart(double) |
97 |
|
*/ |
98 |
public abstract double getAngleStart(); |
public abstract double getAngleStart(); |
99 |
/** Extent in degrees. */ |
|
100 |
|
/** |
101 |
|
* Get the extent angle of the arc in degrees. |
102 |
|
* |
103 |
|
* @return the extent angle |
104 |
|
* @see #setAngleExtent(double) |
105 |
|
*/ |
106 |
public abstract double getAngleExtent(); |
public abstract double getAngleExtent(); |
107 |
|
|
108 |
|
/** |
109 |
|
* Return the closure type of the arc. |
110 |
|
* |
111 |
|
* @return the closure type |
112 |
|
* @see #OPEN |
113 |
|
* @see #CHORD |
114 |
|
* @see #PIE |
115 |
|
* @see #setArcType(int) |
116 |
|
*/ |
117 |
public int getArcType() |
public int getArcType() |
118 |
{ |
{ |
119 |
return type; |
return type; |
120 |
} |
} |
121 |
|
|
122 |
|
/** |
123 |
|
* Returns the starting point of the arc. |
124 |
|
* |
125 |
|
* @return the start point |
126 |
|
*/ |
127 |
public Point2D getStartPoint() |
public Point2D getStartPoint() |
128 |
{ |
{ |
129 |
// XXX Implement. |
double angle = getAngleStart() * (-180 / Math.PI); |
130 |
throw new Error("not implemented"); |
double x = (Math.cos(angle) * getWidth() + getX()) / 2; |
131 |
|
double y = (Math.sin(angle) * getHeight() + getY()) / 2; |
132 |
|
return new Point2D.Double(x, y); |
133 |
} |
} |
134 |
|
|
135 |
|
/** |
136 |
|
* Returns the ending point of the arc. |
137 |
|
* |
138 |
|
* @return the end point |
139 |
|
*/ |
140 |
public Point2D getEndPoint() |
public Point2D getEndPoint() |
141 |
{ |
{ |
142 |
// XXX Implement. |
double angle = (getAngleStart() + getAngleExtent()) * (-180 / Math.PI); |
143 |
throw new Error("not implemented"); |
double x = (Math.cos(angle) * getWidth() + getX()) / 2; |
144 |
|
double y = (Math.sin(angle) * getHeight() + getY()) / 2; |
145 |
|
return new Point2D.Double(x, y); |
146 |
} |
} |
147 |
/** Start, extent in degrees. */ |
|
148 |
|
/** |
149 |
|
* Set the parameters of the arc. The angles are in degrees, and a positive |
150 |
|
* extent sweeps counterclockwise (from the positive x-axis to the negative |
151 |
|
* y-axis). |
152 |
|
* |
153 |
|
* @param x the new x coordinate of the lower left of the bounding box |
154 |
|
* @param y the new y coordinate of the lower left of the bounding box |
155 |
|
* @param w the new width of the bounding box |
156 |
|
* @param h the new height of the bounding box |
157 |
|
* @param start the start angle, in degrees |
158 |
|
* @param extent the arc extent, in degrees |
159 |
|
* @param type one of {@link #OPEN}, {@link #CHORD}, or {@link #PIE} |
160 |
|
* @throws IllegalArgumentException if type is invalid |
161 |
|
*/ |
162 |
public abstract void setArc(double x, double y, double w, double h, |
public abstract void setArc(double x, double y, double w, double h, |
163 |
double start, double extent, int type); |
double start, double extent, int type); |
164 |
|
|
165 |
|
/** |
166 |
|
* Set the parameters of the arc. The angles are in degrees, and a positive |
167 |
|
* extent sweeps counterclockwise (from the positive x-axis to the negative |
168 |
|
* y-axis). |
169 |
|
* |
170 |
|
* @param p the lower left point of the bounding box |
171 |
|
* @param d the dimensions of the bounding box |
172 |
|
* @param start the start angle, in degrees |
173 |
|
* @param extent the arc extent, in degrees |
174 |
|
* @param type one of {@link #OPEN}, {@link #CHORD}, or {@link #PIE} |
175 |
|
* @throws IllegalArgumentException if type is invalid |
176 |
|
* @throws NullPointerException if p or d is null |
177 |
|
*/ |
178 |
public void setArc(Point2D p, Dimension2D d, |
public void setArc(Point2D p, Dimension2D d, |
179 |
double start, double extent, int type) |
double start, double extent, int type) |
180 |
{ |
{ |
181 |
setArc(p.getX(), p.getY(), d.getWidth(), d.getHeight(), |
setArc(p.getX(), p.getY(), d.getWidth(), d.getHeight(), |
182 |
start, extent, type); |
start, extent, type); |
183 |
} |
} |
184 |
|
|
185 |
|
/** |
186 |
|
* Set the parameters of the arc. The angles are in degrees, and a positive |
187 |
|
* extent sweeps counterclockwise (from the positive x-axis to the negative |
188 |
|
* y-axis). |
189 |
|
* |
190 |
|
* @param r the new bounding box |
191 |
|
* @param start the start angle, in degrees |
192 |
|
* @param extent the arc extent, in degrees |
193 |
|
* @param type one of {@link #OPEN}, {@link #CHORD}, or {@link #PIE} |
194 |
|
* @throws IllegalArgumentException if type is invalid |
195 |
|
* @throws NullPointerException if r is null |
196 |
|
*/ |
197 |
public void setArc(Rectangle2D r, double start, double extent, int type) |
public void setArc(Rectangle2D r, double start, double extent, int type) |
198 |
{ |
{ |
199 |
setArc(r.getX(), r.getY(), r.getWidth(), r.getHeight(), |
setArc(r.getX(), r.getY(), r.getWidth(), r.getHeight(), |
200 |
start, extent, type); |
start, extent, type); |
201 |
} |
} |
202 |
|
|
203 |
|
/** |
204 |
|
* Set the parameters of the arc from the given one. |
205 |
|
* |
206 |
|
* @param a the arc to copy |
207 |
|
* @throws NullPointerException if a is null |
208 |
|
*/ |
209 |
public void setArc(Arc2D a) |
public void setArc(Arc2D a) |
210 |
{ |
{ |
211 |
setArc(a.getX(), a.getY(), a.getWidth(), a.getHeight(), |
setArc(a.getX(), a.getY(), a.getWidth(), a.getHeight(), |
212 |
a.getAngleStart(), a.getAngleExtent(), a.getArcType()); |
a.getAngleStart(), a.getAngleExtent(), a.getArcType()); |
213 |
} |
} |
214 |
|
|
215 |
|
/** |
216 |
|
* Set the parameters of the arc. The angles are in degrees, and a positive |
217 |
|
* extent sweeps counterclockwise (from the positive x-axis to the negative |
218 |
|
* y-axis). This controls the center point and radius, so the arc will be |
219 |
|
* circular. |
220 |
|
* |
221 |
|
* @param x the x coordinate of the center of the circle |
222 |
|
* @param y the y coordinate of the center of the circle |
223 |
|
* @param r the radius of the circle |
224 |
|
* @param start the start angle, in degrees |
225 |
|
* @param extent the arc extent, in degrees |
226 |
|
* @param type one of {@link #OPEN}, {@link #CHORD}, or {@link #PIE} |
227 |
|
* @throws IllegalArgumentException if type is invalid |
228 |
|
*/ |
229 |
public void setArcByCenter(double x, double y, double r, |
public void setArcByCenter(double x, double y, double r, |
230 |
double start, double extent, int type) |
double start, double extent, int type) |
231 |
{ |
{ |
232 |
setArc(x - r, y - r, r + r, r + r, start, extent, type); |
setArc(x - r, y - r, r + r, r + r, start, extent, type); |
233 |
} |
} |
234 |
|
|
235 |
|
/** |
236 |
|
* Sets the parameters of the arc by finding the tangents of two lines, and |
237 |
|
* using the specified radius. The arc will be circular, will begin on the |
238 |
|
* tangent point of the line extending from p1 to p2, and will end on the |
239 |
|
* tangent point of the line extending from p2 to p3. |
240 |
|
* |
241 |
|
* XXX What happens if the points are colinear, or the radius negative? |
242 |
|
* |
243 |
|
* @param p1 the first point |
244 |
|
* @param p2 the tangent line intersection point |
245 |
|
* @param p3 the third point |
246 |
|
* @param r the radius of the arc |
247 |
|
* @throws NullPointerException if any point is null |
248 |
|
*/ |
249 |
public void setArcByTangent(Point2D p1, Point2D p2, Point2D p3, double r) |
public void setArcByTangent(Point2D p1, Point2D p2, Point2D p3, double r) |
250 |
{ |
{ |
251 |
// XXX Implement. |
// XXX Implement. |
252 |
throw new Error("not implemented"); |
throw new Error("not implemented"); |
253 |
} |
} |
254 |
|
|
255 |
/** Start in degrees. */ |
/** |
256 |
|
* Set the start, in degrees. |
257 |
|
* |
258 |
|
* @param start the new start angle |
259 |
|
* @see #getAngleStart() |
260 |
|
*/ |
261 |
public abstract void setAngleStart(double start); |
public abstract void setAngleStart(double start); |
262 |
/** Extent in degrees. */ |
|
263 |
|
/** |
264 |
|
* Set the extent, in degrees. |
265 |
|
* |
266 |
|
* @param extent the new extent angle |
267 |
|
* @see #getAngleExtent() |
268 |
|
*/ |
269 |
public abstract void setAngleExtent(double extent); |
public abstract void setAngleExtent(double extent); |
270 |
|
|
271 |
|
/** |
272 |
|
* Sets the starting angle to the angle of the given point relative to |
273 |
|
* the center of the arc. The extent remains constant; in other words, |
274 |
|
* this rotates the arc. |
275 |
|
* |
276 |
|
* @param p the new start point |
277 |
|
* @throws NullPointerException if p is null |
278 |
|
* @see #getStartPoint() |
279 |
|
* @see #getAngleStart() |
280 |
|
*/ |
281 |
public void setAngleStart(Point2D p) |
public void setAngleStart(Point2D p) |
282 |
{ |
{ |
283 |
setAngleStart(Math.atan2(p.getY() - getCenterY(), |
double x = ((p.getX() * 2) - getX()) / getWidth(); |
284 |
p.getX() - getCenterX())); |
double y = ((p.getY() * 2) - getY()) / getHeight(); |
285 |
|
setAngleStart(Math.atan2(y, x) * (-180 / Math.PI)); |
286 |
} |
} |
287 |
|
|
288 |
|
/** |
289 |
|
* Sets the starting and extent angles to those of the given points |
290 |
|
* relative to the center of the arc. The arc will be non-empty, and will |
291 |
|
* extend counterclockwise. |
292 |
|
* |
293 |
|
* @param x1 the first x coordinate |
294 |
|
* @param y1 the first y coordinate |
295 |
|
* @param x2 the second x coordinate |
296 |
|
* @param y2 the second y coordinate |
297 |
|
* @see #setAngleStart(Point2D) |
298 |
|
*/ |
299 |
public void setAngles(double x1, double y1, double x2, double y2) |
public void setAngles(double x1, double y1, double x2, double y2) |
300 |
{ |
{ |
301 |
// XXX Implement. |
// Normalize the points. |
302 |
throw new Error("not implemented"); |
double mx = getX(); |
303 |
|
double my = getY(); |
304 |
|
double mw = getWidth(); |
305 |
|
double mh = getHeight(); |
306 |
|
x1 = ((x1 * 2) - mx) / mw; |
307 |
|
y1 = ((y1 * 2) - my) / mh; |
308 |
|
x2 = ((x2 * 2) - mx) / mw; |
309 |
|
y2 = ((y2 * 2) - my) / mh; |
310 |
|
double start = Math.atan2(y1, x1) * (-180 / Math.PI); |
311 |
|
double extent = Math.atan2(y2, x2) * (-180 / Math.PI) - start; |
312 |
|
if (extent < 0) |
313 |
|
extent += 360; |
314 |
|
setAngleStart(start); |
315 |
|
setAngleExtent(extent); |
316 |
} |
} |
317 |
|
|
318 |
|
/** |
319 |
|
* Sets the starting and extent angles to those of the given points |
320 |
|
* relative to the center of the arc. The arc will be non-empty, and will |
321 |
|
* extend counterclockwise. |
322 |
|
* |
323 |
|
* @param p1 the first point |
324 |
|
* @param p2 the second point |
325 |
|
* @throws NullPointerException if either point is null |
326 |
|
* @see #setAngleStart(Point2D) |
327 |
|
*/ |
328 |
public void setAngles(Point2D p1, Point2D p2) |
public void setAngles(Point2D p1, Point2D p2) |
329 |
{ |
{ |
330 |
setAngles(p1.getX(), p1.getY(), p2.getX(), p2.getY()); |
setAngles(p1.getX(), p1.getY(), p2.getX(), p2.getY()); |
331 |
} |
} |
332 |
|
|
333 |
|
/** |
334 |
|
* Set the closure type of this arc. |
335 |
|
* |
336 |
|
* @param type one of {@link #OPEN}, {@link #CHORD}, or {@link #PIE} |
337 |
|
* @throws IllegalArgumentException if type is invalid |
338 |
|
* @see #getArcType() |
339 |
|
*/ |
340 |
public void setArcType(int type) |
public void setArcType(int type) |
341 |
{ |
{ |
342 |
if (type < OPEN || type > PIE) |
if (type < OPEN || type > PIE) |
343 |
throw new IllegalArgumentException(); |
throw new IllegalArgumentException(); |
344 |
this.type = type; |
this.type = type; |
345 |
} |
} |
346 |
|
|
347 |
|
/** |
348 |
|
* Sets the location and bounds of the ellipse of which this arc is a part. |
349 |
|
* |
350 |
|
* @param x the new x coordinate |
351 |
|
* @param y the new y coordinate |
352 |
|
* @param w the new width |
353 |
|
* @param h the new height |
354 |
|
* @see #getFrame() |
355 |
|
*/ |
356 |
public void setFrame(double x, double y, double w, double h) |
public void setFrame(double x, double y, double w, double h) |
357 |
{ |
{ |
358 |
// XXX Implement. |
setArc(x, y, w, h, getAngleStart(), getAngleExtent(), type); |
|
throw new Error("not implemented"); |
|
359 |
} |
} |
360 |
|
|
361 |
|
/** |
362 |
|
* Gets the bounds of the arc. This is much tighter than |
363 |
|
* <code>getBounds</code>, as it takes into consideration the start and |
364 |
|
* end angles, and the center point of a pie wedge, rather than just the |
365 |
|
* overall ellipse. |
366 |
|
* |
367 |
|
* @return the bounds of the arc |
368 |
|
* @see #getBounds() |
369 |
|
*/ |
370 |
public Rectangle2D getBounds2D() |
public Rectangle2D getBounds2D() |
371 |
{ |
{ |
372 |
// XXX Implement. |
double extent = getAngleExtent(); |
373 |
|
if (Math.abs(extent) >= 360) |
374 |
|
return makeBounds(getX(), getY(), getWidth(), getHeight()); |
375 |
|
// XXX Finish implementing. |
376 |
throw new Error("not implemented"); |
throw new Error("not implemented"); |
377 |
} |
} |
378 |
|
|
379 |
|
/** |
380 |
|
* Construct a bounding box in a precision appropriate for the subclass. |
381 |
|
* |
382 |
|
* @param x the x coordinate |
383 |
|
* @param y the y coordinate |
384 |
|
* @param w the width |
385 |
|
* @param h the height |
386 |
|
* @return the rectangle for use in getBounds2D |
387 |
|
*/ |
388 |
protected abstract Rectangle2D makeBounds(double x, double y, |
protected abstract Rectangle2D makeBounds(double x, double y, |
389 |
double w, double h); |
double w, double h); |
390 |
|
|
391 |
|
/** |
392 |
|
* Tests if the given angle, in degrees, is included in the arc. |
393 |
|
* |
394 |
|
* XXX Does this normalize all angles to -180 - 180 first? |
395 |
|
* |
396 |
|
* @param a the angle to test |
397 |
|
* @return true if it is contained |
398 |
|
*/ |
399 |
public boolean containsAngle(double a) |
public boolean containsAngle(double a) |
400 |
{ |
{ |
401 |
// XXX Implement. |
// XXX Implement. |
402 |
throw new Error("not implemented"); |
throw new Error("not implemented"); |
403 |
} |
} |
404 |
|
|
405 |
|
/** |
406 |
|
* Determines if the arc contains the given point. If the bounding box |
407 |
|
* is empty, then this will return false. |
408 |
|
* |
409 |
|
* @param x the x coordinate to test |
410 |
|
* @param y the y coordinate to test |
411 |
|
* @return true if the point is inside the arc |
412 |
|
*/ |
413 |
public boolean contains(double x, double y) |
public boolean contains(double x, double y) |
414 |
{ |
{ |
415 |
// XXX Implement. |
double w = getWidth(); |
416 |
|
double h = getHeight(); |
417 |
|
if (w <= 0 || h <= 0) |
418 |
|
return false; |
419 |
|
// XXX Finish implementing. |
420 |
throw new Error("not implemented"); |
throw new Error("not implemented"); |
421 |
} |
} |
422 |
|
|
423 |
|
/** |
424 |
|
* Tests if a given rectangle intersects the area of the arc. |
425 |
|
* |
426 |
|
* @param x the x coordinate of the rectangle |
427 |
|
* @param y the y coordinate of the rectangle |
428 |
|
* @param w the width of the rectangle |
429 |
|
* @param h the height of the rectangle |
430 |
|
* @return true if the two shapes share common points |
431 |
|
*/ |
432 |
public boolean intersects(double x, double y, double w, double h) |
public boolean intersects(double x, double y, double w, double h) |
433 |
{ |
{ |
434 |
// XXX Implement. |
double mw = getWidth(); |
435 |
|
double mh = getHeight(); |
436 |
|
if (mw <= 0 || mh <= 0 || w <= 0 || h <= 0) |
437 |
|
return false; |
438 |
|
// XXX Finish implementing. |
439 |
throw new Error("not implemented"); |
throw new Error("not implemented"); |
440 |
} |
} |
441 |
|
|
442 |
|
/** |
443 |
|
* Tests if a given rectangle is contained in the area of the arc. |
444 |
|
* |
445 |
|
* @param x the x coordinate of the rectangle |
446 |
|
* @param y the y coordinate of the rectangle |
447 |
|
* @param w the width of the rectangle |
448 |
|
* @param h the height of the rectangle |
449 |
|
* @return true if the arc contains the rectangle |
450 |
|
*/ |
451 |
public boolean contains(double x, double y, double w, double h) |
public boolean contains(double x, double y, double w, double h) |
452 |
{ |
{ |
453 |
// XXX Implement. |
double mw = getWidth(); |
454 |
|
double mh = getHeight(); |
455 |
|
if (mw <= 0 || mh <= 0 || w <= 0 || h <= 0) |
456 |
|
return false; |
457 |
|
// XXX Finish implementing. |
458 |
throw new Error("not implemented"); |
throw new Error("not implemented"); |
459 |
} |
} |
460 |
|
|
461 |
|
/** |
462 |
|
* Tests if a given rectangle is contained in the area of the arc. |
463 |
|
* |
464 |
|
* @param r the rectangle |
465 |
|
* @return true if the arc contains the rectangle |
466 |
|
*/ |
467 |
public boolean contains(Rectangle2D r) |
public boolean contains(Rectangle2D r) |
468 |
{ |
{ |
469 |
return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight()); |
return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight()); |
470 |
} |
} |
471 |
|
|
472 |
|
/** |
473 |
|
* Returns an iterator over this arc, with an optional transformation. |
474 |
|
* This iterator is threadsafe, so future modifications to the arc do not |
475 |
|
* affect the iteration. |
476 |
|
* |
477 |
|
* @param at the transformation, or null |
478 |
|
* @return a path iterator |
479 |
|
*/ |
480 |
public PathIterator getPathIterator(AffineTransform at) |
public PathIterator getPathIterator(AffineTransform at) |
481 |
{ |
{ |
482 |
return new ArcIterator(this, at); |
return new ArcIterator(this, at); |
483 |
} |
} |
484 |
|
|
485 |
/** |
/** |
486 |
* STUBS ONLY |
* This class is used to iterate over an arc. Since ellipses are a subclass |
487 |
* Used by Ellipse2D as well. |
* of arcs, this is used by Ellipse2D as well. |
488 |
|
* |
489 |
|
* @author Eric Blake <ebb9@email.byu.edu> |
490 |
*/ |
*/ |
491 |
static final class ArcIterator implements PathIterator |
static final class ArcIterator implements PathIterator |
492 |
{ |
{ |
493 |
/** Current coordinate. */ |
/** The current iteration. */ |
494 |
private int current; |
private int current; |
495 |
/** Last iteration. */ |
|
496 |
|
/** The last iteration. */ |
497 |
private final int limit; |
private final int limit; |
498 |
|
|
499 |
|
/** The optional transformation. */ |
500 |
private final AffineTransform xform; |
private final AffineTransform xform; |
501 |
|
|
502 |
|
/** The x coordinate of the bounding box. */ |
503 |
private final double x; |
private final double x; |
504 |
|
|
505 |
|
/** The y coordinate of the bounding box. */ |
506 |
private final double y; |
private final double y; |
507 |
|
|
508 |
|
/** The width of the bounding box. */ |
509 |
private final double w; |
private final double w; |
510 |
|
|
511 |
|
/** The height of the bounding box. */ |
512 |
private final double h; |
private final double h; |
513 |
/** Start in radians. */ |
|
514 |
|
/** The start angle, in radians (not degrees). */ |
515 |
private final double start; |
private final double start; |
516 |
/** Extent in radians. */ |
|
517 |
|
/** The extent angle, in radians (not degrees). */ |
518 |
private final double extent; |
private final double extent; |
519 |
|
|
520 |
|
/** The arc closure type. */ |
521 |
private final int type; |
private final int type; |
522 |
|
|
523 |
|
/** |
524 |
|
* Construct a new iterator over an arc. |
525 |
|
* |
526 |
|
* @param a the arc |
527 |
|
* @param xform the transform |
528 |
|
*/ |
529 |
ArcIterator(Arc2D a, AffineTransform xform) |
ArcIterator(Arc2D a, AffineTransform xform) |
530 |
{ |
{ |
531 |
this.xform = xform; |
this.xform = xform; |
551 |
limit = type + 4; |
limit = type + 4; |
552 |
} |
} |
553 |
|
|
554 |
|
/** |
555 |
|
* Construct a new iterator over an ellipse. |
556 |
|
* |
557 |
|
* @param e the ellipse |
558 |
|
* @param xform the transform |
559 |
|
*/ |
560 |
ArcIterator(Ellipse2D e, AffineTransform xform) |
ArcIterator(Ellipse2D e, AffineTransform xform) |
561 |
{ |
{ |
562 |
this.xform = xform; |
this.xform = xform; |
570 |
limit = (w < 0 || h < 0) ? -1 : 5; |
limit = (w < 0 || h < 0) ? -1 : 5; |
571 |
} |
} |
572 |
|
|
573 |
|
/** |
574 |
|
* Return the winding rule. |
575 |
|
* |
576 |
|
* @return {@link PathIterator#WIND_NON_ZERO} |
577 |
|
*/ |
578 |
public int getWindingRule() |
public int getWindingRule() |
579 |
{ |
{ |
580 |
return WIND_NON_ZERO; |
return WIND_NON_ZERO; |
581 |
} |
} |
582 |
|
|
583 |
|
/** |
584 |
|
* Test if the iteration is complete. |
585 |
|
* |
586 |
|
* @return true if more segments exist |
587 |
|
*/ |
588 |
public boolean isDone() |
public boolean isDone() |
589 |
{ |
{ |
590 |
return current > limit; |
return current > limit; |
591 |
} |
} |
592 |
|
|
593 |
|
/** |
594 |
|
* Advance the iterator. |
595 |
|
*/ |
596 |
public void next() |
public void next() |
597 |
{ |
{ |
598 |
current++; |
current++; |
599 |
} |
} |
600 |
|
|
601 |
|
/** |
602 |
|
* Put the current segment into the array, and return the segment type. |
603 |
|
* |
604 |
|
* @param coords an array of 6 elements |
605 |
|
* @return the segment type |
606 |
|
* @throws NullPointerException if coords is null |
607 |
|
* @throws ArrayIndexOutOfBoundsException if coords is too small |
608 |
|
*/ |
609 |
public int currentSegment(float[] coords) |
public int currentSegment(float[] coords) |
610 |
{ |
{ |
611 |
if (current > limit) |
if (current > limit) |
612 |
throw new NoSuchElementException("arc iterator out of bounds"); |
throw new NoSuchElementException("arc iterator out of bounds"); |
613 |
if (current == 0) |
if (current == 0) |
614 |
{ |
{ |
615 |
// XXX Fill coords[0-1] with starting point. |
coords[0] = (float) (Math.cos(start) * w + x) / 2; |
616 |
coords[0] = (float) 0; |
coords[1] = (float) (Math.sin(start) * h + y) / 2; |
|
coords[1] = (float) 0; |
|
617 |
if (xform != null) |
if (xform != null) |
618 |
xform.transform(coords, 0, coords, 0, 1); |
xform.transform(coords, 0, coords, 0, 1); |
619 |
return SEG_MOVETO; |
return SEG_MOVETO; |
640 |
return SEG_CUBICTO; |
return SEG_CUBICTO; |
641 |
} |
} |
642 |
|
|
643 |
|
/** |
644 |
|
* Put the current segment into the array, and return the segment type. |
645 |
|
* |
646 |
|
* @param coords an array of 6 elements |
647 |
|
* @return the segment type |
648 |
|
* @throws NullPointerException if coords is null |
649 |
|
* @throws ArrayIndexOutOfBoundsException if coords is too small |
650 |
|
*/ |
651 |
public int currentSegment(double[] coords) |
public int currentSegment(double[] coords) |
652 |
{ |
{ |
653 |
if (current > limit) |
if (current > limit) |
654 |
throw new NoSuchElementException("arc iterator out of bounds"); |
throw new NoSuchElementException("arc iterator out of bounds"); |
655 |
if (current == 0) |
if (current == 0) |
656 |
{ |
{ |
657 |
// XXX Fill coords[0-1] with starting point. |
coords[0] = (Math.cos(start) * w + x) / 2; |
658 |
coords[0] = 0; |
coords[1] = (Math.sin(start) * h + y) / 2; |
|
coords[1] = 0; |
|
659 |
if (xform != null) |
if (xform != null) |
660 |
xform.transform(coords, 0, coords, 0, 1); |
xform.transform(coords, 0, coords, 0, 1); |
661 |
return SEG_MOVETO; |
return SEG_MOVETO; |
684 |
} // class ArcIterator |
} // class ArcIterator |
685 |
|
|
686 |
/** |
/** |
687 |
* STUBS ONLY |
* This class implements an arc in double precision. |
688 |
|
* |
689 |
|
* @author Eric Blake <ebb9@email.byu.edu |
690 |
|
* @since 1.2 |
691 |
*/ |
*/ |
692 |
public static class Double extends Arc2D |
public static class Double extends Arc2D |
693 |
{ |
{ |
694 |
|
/** The x coordinate of the box bounding the ellipse of this arc. */ |
695 |
public double x; |
public double x; |
696 |
|
|
697 |
|
/** The y coordinate of the box bounding the ellipse of this arc. */ |
698 |
public double y; |
public double y; |
699 |
|
|
700 |
|
/** The width of the box bounding the ellipse of this arc. */ |
701 |
public double width; |
public double width; |
702 |
|
|
703 |
|
/** The height of the box bounding the ellipse of this arc. */ |
704 |
public double height; |
public double height; |
705 |
|
|
706 |
|
/** The start angle of this arc, in degrees. */ |
707 |
public double start; |
public double start; |
708 |
|
|
709 |
|
/** The extent angle of this arc, in degrees. */ |
710 |
public double extent; |
public double extent; |
711 |
|
|
712 |
|
/** |
713 |
|
* Create a new, open arc at (0,0) with 0 extent. |
714 |
|
*/ |
715 |
public Double() |
public Double() |
716 |
{ |
{ |
717 |
super(OPEN); |
super(OPEN); |
718 |
} |
} |
719 |
|
|
720 |
|
/** |
721 |
|
* Create a new arc of the given type at (0,0) with 0 extent. |
722 |
|
* |
723 |
|
* @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE} |
724 |
|
* @throws IllegalArgumentException if type is invalid |
725 |
|
*/ |
726 |
public Double(int type) |
public Double(int type) |
727 |
{ |
{ |
728 |
super(type); |
super(type); |
729 |
} |
} |
730 |
|
|
731 |
|
/** |
732 |
|
* Create a new arc with the given dimensions. |
733 |
|
* |
734 |
|
* @param x the x coordinate |
735 |
|
* @param y the y coordinate |
736 |
|
* @param w the width |
737 |
|
* @param h the height |
738 |
|
* @param start the start angle, in degrees |
739 |
|
* @param extent the extent, in degrees |
740 |
|
* @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE} |
741 |
|
* @throws IllegalArgumentException if type is invalid |
742 |
|
*/ |
743 |
public Double(double x, double y, double w, double h, |
public Double(double x, double y, double w, double h, |
744 |
double start, double extent, int type) |
double start, double extent, int type) |
745 |
{ |
{ |
752 |
this.extent = extent; |
this.extent = extent; |
753 |
} |
} |
754 |
|
|
755 |
|
/** |
756 |
|
* Create a new arc with the given dimensions. |
757 |
|
* |
758 |
|
* @param r the bounding box |
759 |
|
* @param start the start angle, in degrees |
760 |
|
* @param extent the extent, in degrees |
761 |
|
* @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE} |
762 |
|
* @throws IllegalArgumentException if type is invalid |
763 |
|
* @throws NullPointerException if r is null |
764 |
|
*/ |
765 |
public Double(Rectangle2D r, double start, double extent, int type) |
public Double(Rectangle2D r, double start, double extent, int type) |
766 |
{ |
{ |
767 |
super(type); |
super(type); |
773 |
this.extent = extent; |
this.extent = extent; |
774 |
} |
} |
775 |
|
|
776 |
|
/** |
777 |
|
* Return the x coordinate of the bounding box. |
778 |
|
* |
779 |
|
* @return the value of x |
780 |
|
*/ |
781 |
public double getX() |
public double getX() |
782 |
{ |
{ |
783 |
return x; |
return x; |
784 |
} |
} |
785 |
|
|
786 |
|
/** |
787 |
|
* Return the y coordinate of the bounding box. |
788 |
|
* |
789 |
|
* @return the value of y |
790 |
|
*/ |
791 |
public double getY() |
public double getY() |
792 |
{ |
{ |
793 |
return y; |
return y; |
794 |
} |
} |
795 |
|
|
796 |
|
/** |
797 |
|
* Return the width of the bounding box. |
798 |
|
* |
799 |
|
* @return the value of width |
800 |
|
*/ |
801 |
public double getWidth() |
public double getWidth() |
802 |
{ |
{ |
803 |
return width; |
return width; |
804 |
} |
} |
805 |
|
|
806 |
|
/** |
807 |
|
* Return the height of the bounding box. |
808 |
|
* |
809 |
|
* @return the value of height |
810 |
|
*/ |
811 |
public double getHeight() |
public double getHeight() |
812 |
{ |
{ |
813 |
return height; |
return height; |
814 |
} |
} |
815 |
|
|
816 |
|
/** |
817 |
|
* Return the start angle of the arc, in degrees. |
818 |
|
* |
819 |
|
* @return the value of start |
820 |
|
*/ |
821 |
public double getAngleStart() |
public double getAngleStart() |
822 |
{ |
{ |
823 |
return start; |
return start; |
824 |
} |
} |
825 |
|
|
826 |
|
/** |
827 |
|
* Return the extent of the arc, in degrees. |
828 |
|
* |
829 |
|
* @return the value of extent |
830 |
|
*/ |
831 |
public double getAngleExtent() |
public double getAngleExtent() |
832 |
{ |
{ |
833 |
return extent; |
return extent; |
834 |
} |
} |
835 |
|
|
836 |
|
/** |
837 |
|
* Tests if the arc contains points. |
838 |
|
* |
839 |
|
* @return true if the arc has no interior |
840 |
|
*/ |
841 |
public boolean isEmpty() |
public boolean isEmpty() |
842 |
{ |
{ |
843 |
return width <= 0 || height <= 0; |
return width <= 0 || height <= 0; |
844 |
} |
} |
845 |
|
|
846 |
|
/** |
847 |
|
* Sets the arc to the given dimensions. |
848 |
|
* |
849 |
|
* @param x the x coordinate |
850 |
|
* @param y the y coordinate |
851 |
|
* @param w the width |
852 |
|
* @param h the height |
853 |
|
* @param start the start angle, in degrees |
854 |
|
* @param extent the extent, in degrees |
855 |
|
* @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE} |
856 |
|
* @throws IllegalArgumentException if type is invalid |
857 |
|
*/ |
858 |
public void setArc(double x, double y, double w, double h, |
public void setArc(double x, double y, double w, double h, |
859 |
double start, double extent, int type) |
double start, double extent, int type) |
860 |
{ |
{ |
866 |
this.extent = extent; |
this.extent = extent; |
867 |
setArcType(type); |
setArcType(type); |
868 |
} |
} |
869 |
|
|
870 |
|
/** |
871 |
|
* Sets the start angle of the arc. |
872 |
|
* |
873 |
|
* @param start the new start angle |
874 |
|
*/ |
875 |
public void setAngleStart(double start) |
public void setAngleStart(double start) |
876 |
{ |
{ |
877 |
this.start = start; |
this.start = start; |
878 |
} |
} |
879 |
|
|
880 |
|
/** |
881 |
|
* Sets the extent angle of the arc. |
882 |
|
* |
883 |
|
* @param start the new extent angle |
884 |
|
*/ |
885 |
public void setAngleExtent(double extent) |
public void setAngleExtent(double extent) |
886 |
{ |
{ |
887 |
this.extent = extent; |
this.extent = extent; |
888 |
} |
} |
889 |
|
|
890 |
|
/** |
891 |
|
* Creates a tight bounding box given dimensions that more precise than |
892 |
|
* the bounding box of the ellipse. |
893 |
|
* |
894 |
|
* @param x the x coordinate |
895 |
|
* @param y the y coordinate |
896 |
|
* @param w the width |
897 |
|
* @param h the height |
898 |
|
*/ |
899 |
protected Rectangle2D makeBounds(double x, double y, double w, double h) |
protected Rectangle2D makeBounds(double x, double y, double w, double h) |
900 |
{ |
{ |
901 |
return new Rectangle2D.Double(x, y, w, h); |
return new Rectangle2D.Double(x, y, w, h); |
903 |
} // class Double |
} // class Double |
904 |
|
|
905 |
/** |
/** |
906 |
* STUBS ONLY |
* This class implements an arc in float precision. |
907 |
|
* |
908 |
|
* @author Eric Blake <ebb9@email.byu.edu |
909 |
|
* @since 1.2 |
910 |
*/ |
*/ |
911 |
public static class Float extends Arc2D |
public static class Float extends Arc2D |
912 |
{ |
{ |
913 |
|
/** The x coordinate of the box bounding the ellipse of this arc. */ |
914 |
public float x; |
public float x; |
915 |
|
|
916 |
|
/** The y coordinate of the box bounding the ellipse of this arc. */ |
917 |
public float y; |
public float y; |
918 |
|
|
919 |
|
/** The width of the box bounding the ellipse of this arc. */ |
920 |
public float width; |
public float width; |
921 |
|
|
922 |
|
/** The height of the box bounding the ellipse of this arc. */ |
923 |
public float height; |
public float height; |
924 |
|
|
925 |
|
/** The start angle of this arc, in degrees. */ |
926 |
public float start; |
public float start; |
927 |
|
|
928 |
|
/** The extent angle of this arc, in degrees. */ |
929 |
public float extent; |
public float extent; |
930 |
|
|
931 |
|
/** |
932 |
|
* Create a new, open arc at (0,0) with 0 extent. |
933 |
|
*/ |
934 |
public Float() |
public Float() |
935 |
{ |
{ |
936 |
super(OPEN); |
super(OPEN); |
937 |
} |
} |
938 |
|
|
939 |
|
/** |
940 |
|
* Create a new arc of the given type at (0,0) with 0 extent. |
941 |
|
* |
942 |
|
* @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE} |
943 |
|
* @throws IllegalArgumentException if type is invalid |
944 |
|
*/ |
945 |
public Float(int type) |
public Float(int type) |
946 |
{ |
{ |
947 |
super(type); |
super(type); |
948 |
} |
} |
949 |
|
|
950 |
|
/** |
951 |
|
* Create a new arc with the given dimensions. |
952 |
|
* |
953 |
|
* @param x the x coordinate |
954 |
|
* @param y the y coordinate |
955 |
|
* @param w the width |
956 |
|
* @param h the height |
957 |
|
* @param start the start angle, in degrees |
958 |
|
* @param extent the extent, in degrees |
959 |
|
* @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE} |
960 |
|
* @throws IllegalArgumentException if type is invalid |
961 |
|
*/ |
962 |
public Float(float x, float y, float w, float h, |
public Float(float x, float y, float w, float h, |
963 |
float start, float extent, int type) |
float start, float extent, int type) |
964 |
{ |
{ |
965 |
super(type); |
super(type); |
966 |
this.x = x; |
this.x = x; |
971 |
this.extent = extent; |
this.extent = extent; |
972 |
} |
} |
973 |
|
|
974 |
|
/** |
975 |
|
* Create a new arc with the given dimensions. |
976 |
|
* |
977 |
|
* @param r the bounding box |
978 |
|
* @param start the start angle, in degrees |
979 |
|
* @param extent the extent, in degrees |
980 |
|
* @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE} |
981 |
|
* @throws IllegalArgumentException if type is invalid |
982 |
|
* @throws NullPointerException if r is null |
983 |
|
*/ |
984 |
public Float(Rectangle2D r, float start, float extent, int type) |
public Float(Rectangle2D r, float start, float extent, int type) |
985 |
{ |
{ |
986 |
super(type); |
super(type); |
992 |
this.extent = extent; |
this.extent = extent; |
993 |
} |
} |
994 |
|
|
995 |
|
/** |
996 |
|
* Return the x coordinate of the bounding box. |
997 |
|
* |
998 |
|
* @return the value of x |
999 |
|
*/ |
1000 |
public double getX() |
public double getX() |
1001 |
{ |
{ |
1002 |
return x; |
return x; |
1003 |
} |
} |
1004 |
|
|
1005 |
|
/** |
1006 |
|
* Return the y coordinate of the bounding box. |
1007 |
|
* |
1008 |
|
* @return the value of y |
1009 |
|
*/ |
1010 |
public double getY() |
public double getY() |
1011 |
{ |
{ |
1012 |
return y; |
return y; |
1013 |
} |
} |
1014 |
|
|
1015 |
|
/** |
1016 |
|
* Return the width of the bounding box. |
1017 |
|
* |
1018 |
|
* @return the value of width |
1019 |
|
*/ |
1020 |
public double getWidth() |
public double getWidth() |
1021 |
{ |
{ |
1022 |
return width; |
return width; |
1023 |
} |
} |
1024 |
|
|
1025 |
|
/** |
1026 |
|
* Return the height of the bounding box. |
1027 |
|
* |
1028 |
|
* @return the value of height |
1029 |
|
*/ |
1030 |
public double getHeight() |
public double getHeight() |
1031 |
{ |
{ |
1032 |
return height; |
return height; |
1033 |
} |
} |
1034 |
|
|
1035 |
|
/** |
1036 |
|
* Return the start angle of the arc, in degrees. |
1037 |
|
* |
1038 |
|
* @return the value of start |
1039 |
|
*/ |
1040 |
public double getAngleStart() |
public double getAngleStart() |
1041 |
{ |
{ |
1042 |
return start; |
return start; |
1043 |
} |
} |
1044 |
|
|
1045 |
|
/** |
1046 |
|
* Return the extent of the arc, in degrees. |
1047 |
|
* |
1048 |
|
* @return the value of extent |
1049 |
|
*/ |
1050 |
public double getAngleExtent() |
public double getAngleExtent() |
1051 |
{ |
{ |
1052 |
return extent; |
return extent; |
1053 |
} |
} |
1054 |
|
|
1055 |
|
/** |
1056 |
|
* Tests if the arc contains points. |
1057 |
|
* |
1058 |
|
* @return true if the arc has no interior |
1059 |
|
*/ |
1060 |
public boolean isEmpty() |
public boolean isEmpty() |
1061 |
{ |
{ |
1062 |
return width <= 0 || height <= 0; |
return width <= 0 || height <= 0; |
1063 |
} |
} |
1064 |
|
|
1065 |
|
/** |
1066 |
|
* Sets the arc to the given dimensions. |
1067 |
|
* |
1068 |
|
* @param x the x coordinate |
1069 |
|
* @param y the y coordinate |
1070 |
|
* @param w the width |
1071 |
|
* @param h the height |
1072 |
|
* @param start the start angle, in degrees |
1073 |
|
* @param extent the extent, in degrees |
1074 |
|
* @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE} |
1075 |
|
* @throws IllegalArgumentException if type is invalid |
1076 |
|
*/ |
1077 |
public void setArc(double x, double y, double w, double h, |
public void setArc(double x, double y, double w, double h, |
1078 |
double start, double extent, int type) |
double start, double extent, int type) |
1079 |
{ |
{ |
1085 |
this.extent = (float) extent; |
this.extent = (float) extent; |
1086 |
setArcType(type); |
setArcType(type); |
1087 |
} |
} |
1088 |
|
|
1089 |
|
/** |
1090 |
|
* Sets the start angle of the arc. |
1091 |
|
* |
1092 |
|
* @param start the new start angle |
1093 |
|
*/ |
1094 |
public void setAngleStart(double start) |
public void setAngleStart(double start) |
1095 |
{ |
{ |
1096 |
this.start = (float) start; |
this.start = (float) start; |
1097 |
} |
} |
1098 |
|
|
1099 |
|
/** |
1100 |
|
* Sets the extent angle of the arc. |
1101 |
|
* |
1102 |
|
* @param start the new extent angle |
1103 |
|
*/ |
1104 |
public void setAngleExtent(double extent) |
public void setAngleExtent(double extent) |
1105 |
{ |
{ |
1106 |
this.extent = (float) extent; |
this.extent = (float) extent; |
1107 |
} |
} |
1108 |
|
|
1109 |
|
/** |
1110 |
|
* Creates a tight bounding box given dimensions that more precise than |
1111 |
|
* the bounding box of the ellipse. |
1112 |
|
* |
1113 |
|
* @param x the x coordinate |
1114 |
|
* @param y the y coordinate |
1115 |
|
* @param w the width |
1116 |
|
* @param h the height |
1117 |
|
*/ |
1118 |
protected Rectangle2D makeBounds(double x, double y, double w, double h) |
protected Rectangle2D makeBounds(double x, double y, double w, double h) |
1119 |
{ |
{ |
1120 |
return new Rectangle2D.Float(x, y, w, h); |
return new Rectangle2D.Float((float) x, (float) y, (float) w, (float) h); |
1121 |
} |
} |
1122 |
} // class Float |
} // class Float |
1123 |
} // class Arc2D |
} // class Arc2D |