1 |
/* CubicCurve2D.java -- represents a parameterized cubic curve in 2-D space |
/* CubicCurve2D.java -- represents a parameterized cubic curve in 2-D space |
2 |
Copyright (C) 2002, 2003 Free Software Foundation |
Copyright (C) 2002, 2003, 2004 Free Software Foundation |
3 |
|
|
4 |
This file is part of GNU Classpath. |
This file is part of GNU Classpath. |
5 |
|
|
35 |
obligated to do so. If you do not wish to do so, delete this |
obligated to do so. If you do not wish to do so, delete this |
36 |
exception statement from your version. */ |
exception statement from your version. */ |
37 |
|
|
|
|
|
38 |
package java.awt.geom; |
package java.awt.geom; |
39 |
|
|
40 |
import java.awt.Rectangle; |
import java.awt.Rectangle; |
52 |
* @author Eric Blake (ebb9@email.byu.edu) |
* @author Eric Blake (ebb9@email.byu.edu) |
53 |
* @author Graydon Hoare (graydon@redhat.com) |
* @author Graydon Hoare (graydon@redhat.com) |
54 |
* @author Sascha Brawer (brawer@dandelis.ch) |
* @author Sascha Brawer (brawer@dandelis.ch) |
55 |
|
* @author Sven de Marothy (sven@physto.se) |
56 |
* |
* |
57 |
* @since 1.2 |
* @since 1.2 |
58 |
*/ |
*/ |
59 |
public abstract class CubicCurve2D |
public abstract class CubicCurve2D implements Shape, Cloneable |
|
implements Shape, Cloneable |
|
60 |
{ |
{ |
61 |
|
private static final double BIG_VALUE = java.lang.Double.MAX_VALUE / 10.0; |
62 |
|
|
63 |
/** |
/** |
64 |
* Constructs a new CubicCurve2D. Typical users will want to |
* Constructs a new CubicCurve2D. Typical users will want to |
65 |
* construct instances of a subclass, such as {@link |
* construct instances of a subclass, such as {@link |
69 |
{ |
{ |
70 |
} |
} |
71 |
|
|
|
|
|
72 |
/** |
/** |
73 |
* Returns the <i>x</i> coordinate of the curve’s start |
* Returns the <i>x</i> coordinate of the curve’s start |
74 |
* point. |
* point. |
75 |
*/ |
*/ |
76 |
public abstract double getX1(); |
public abstract double getX1(); |
77 |
|
|
|
|
|
78 |
/** |
/** |
79 |
* Returns the <i>y</i> coordinate of the curve’s start |
* Returns the <i>y</i> coordinate of the curve’s start |
80 |
* point. |
* point. |
81 |
*/ |
*/ |
82 |
public abstract double getY1(); |
public abstract double getY1(); |
83 |
|
|
|
|
|
84 |
/** |
/** |
85 |
* Returns the curve’s start point. |
* Returns the curve’s start point. |
86 |
*/ |
*/ |
87 |
public abstract Point2D getP1(); |
public abstract Point2D getP1(); |
88 |
|
|
|
|
|
89 |
/** |
/** |
90 |
* Returns the <i>x</i> coordinate of the curve’s first |
* Returns the <i>x</i> coordinate of the curve’s first |
91 |
* control point. |
* control point. |
92 |
*/ |
*/ |
93 |
public abstract double getCtrlX1(); |
public abstract double getCtrlX1(); |
94 |
|
|
|
|
|
95 |
/** |
/** |
96 |
* Returns the <i>y</i> coordinate of the curve’s first |
* Returns the <i>y</i> coordinate of the curve’s first |
97 |
* control point. |
* control point. |
98 |
*/ |
*/ |
99 |
public abstract double getCtrlY1(); |
public abstract double getCtrlY1(); |
100 |
|
|
|
|
|
101 |
/** |
/** |
102 |
* Returns the curve’s first control point. |
* Returns the curve’s first control point. |
103 |
*/ |
*/ |
104 |
public abstract Point2D getCtrlP1(); |
public abstract Point2D getCtrlP1(); |
105 |
|
|
|
|
|
106 |
/** |
/** |
107 |
* Returns the <i>x</i> coordinate of the curve’s second |
* Returns the <i>x</i> coordinate of the curve’s second |
108 |
* control point. |
* control point. |
109 |
*/ |
*/ |
110 |
public abstract double getCtrlX2(); |
public abstract double getCtrlX2(); |
111 |
|
|
|
|
|
112 |
/** |
/** |
113 |
* Returns the <i>y</i> coordinate of the curve’s second |
* Returns the <i>y</i> coordinate of the curve’s second |
114 |
* control point. |
* control point. |
115 |
*/ |
*/ |
116 |
public abstract double getCtrlY2(); |
public abstract double getCtrlY2(); |
117 |
|
|
|
|
|
118 |
/** |
/** |
119 |
* Returns the curve’s second control point. |
* Returns the curve’s second control point. |
120 |
*/ |
*/ |
121 |
public abstract Point2D getCtrlP2(); |
public abstract Point2D getCtrlP2(); |
122 |
|
|
|
|
|
123 |
/** |
/** |
124 |
* Returns the <i>x</i> coordinate of the curve’s end |
* Returns the <i>x</i> coordinate of the curve’s end |
125 |
* point. |
* point. |
126 |
*/ |
*/ |
127 |
public abstract double getX2(); |
public abstract double getX2(); |
128 |
|
|
|
|
|
129 |
/** |
/** |
130 |
* Returns the <i>y</i> coordinate of the curve’s end |
* Returns the <i>y</i> coordinate of the curve’s end |
131 |
* point. |
* point. |
132 |
*/ |
*/ |
133 |
public abstract double getY2(); |
public abstract double getY2(); |
134 |
|
|
|
|
|
135 |
/** |
/** |
136 |
* Returns the curve’s end point. |
* Returns the curve’s end point. |
137 |
*/ |
*/ |
138 |
public abstract Point2D getP2(); |
public abstract Point2D getP2(); |
139 |
|
|
|
|
|
140 |
/** |
/** |
141 |
* Changes the curve geometry, separately specifying each coordinate |
* Changes the curve geometry, separately specifying each coordinate |
142 |
* value. |
* value. |
171 |
public abstract void setCurve(double x1, double y1, double cx1, double cy1, |
public abstract void setCurve(double x1, double y1, double cx1, double cy1, |
172 |
double cx2, double cy2, double x2, double y2); |
double cx2, double cy2, double x2, double y2); |
173 |
|
|
|
|
|
174 |
/** |
/** |
175 |
* Changes the curve geometry, specifying coordinate values in an |
* Changes the curve geometry, specifying coordinate values in an |
176 |
* array. |
* array. |
193 |
*/ |
*/ |
194 |
public void setCurve(double[] coords, int offset) |
public void setCurve(double[] coords, int offset) |
195 |
{ |
{ |
196 |
setCurve(coords[offset++], coords[offset++], |
setCurve(coords[offset++], coords[offset++], coords[offset++], |
197 |
coords[offset++], coords[offset++], |
coords[offset++], coords[offset++], coords[offset++], |
|
coords[offset++], coords[offset++], |
|
198 |
coords[offset++], coords[offset++]); |
coords[offset++], coords[offset++]); |
199 |
} |
} |
200 |
|
|
|
|
|
201 |
/** |
/** |
202 |
* Changes the curve geometry, specifying coordinate values in |
* Changes the curve geometry, specifying coordinate values in |
203 |
* separate Point objects. |
* separate Point objects. |
217 |
*/ |
*/ |
218 |
public void setCurve(Point2D p1, Point2D c1, Point2D c2, Point2D p2) |
public void setCurve(Point2D p1, Point2D c1, Point2D c2, Point2D p2) |
219 |
{ |
{ |
220 |
setCurve(p1.getX(), p1.getY(), c1.getX(), c1.getY(), |
setCurve(p1.getX(), p1.getY(), c1.getX(), c1.getY(), c2.getX(), c2.getY(), |
221 |
c2.getX(), c2.getY(), p2.getX(), p2.getY()); |
p2.getX(), p2.getY()); |
222 |
} |
} |
223 |
|
|
|
|
|
224 |
/** |
/** |
225 |
* Changes the curve geometry, specifying coordinate values in an |
* Changes the curve geometry, specifying coordinate values in an |
226 |
* array of Point objects. |
* array of Point objects. |
242 |
*/ |
*/ |
243 |
public void setCurve(Point2D[] pts, int offset) |
public void setCurve(Point2D[] pts, int offset) |
244 |
{ |
{ |
245 |
setCurve(pts[offset].getX(), pts[offset++].getY(), |
setCurve(pts[offset].getX(), pts[offset++].getY(), pts[offset].getX(), |
246 |
pts[offset].getX(), pts[offset++].getY(), |
pts[offset++].getY(), pts[offset].getX(), pts[offset++].getY(), |
|
pts[offset].getX(), pts[offset++].getY(), |
|
247 |
pts[offset].getX(), pts[offset++].getY()); |
pts[offset].getX(), pts[offset++].getY()); |
248 |
} |
} |
|
|
|
249 |
|
|
250 |
/** |
/** |
251 |
* Changes the curve geometry to that of another curve. |
* Changes the curve geometry to that of another curve. |
258 |
c.getCtrlX2(), c.getCtrlY2(), c.getX2(), c.getY2()); |
c.getCtrlX2(), c.getCtrlY2(), c.getX2(), c.getY2()); |
259 |
} |
} |
260 |
|
|
|
|
|
261 |
/** |
/** |
262 |
* Calculates the squared flatness of a cubic curve, directly |
* Calculates the squared flatness of a cubic curve, directly |
263 |
* specifying each coordinate value. The flatness is the maximal |
* specifying each coordinate value. The flatness is the maximal |
290 |
Line2D.ptSegDistSq(x1, y1, x2, y2, cx2, cy2)); |
Line2D.ptSegDistSq(x1, y1, x2, y2, cx2, cy2)); |
291 |
} |
} |
292 |
|
|
|
|
|
293 |
/** |
/** |
294 |
* Calculates the flatness of a cubic curve, directly specifying |
* Calculates the flatness of a cubic curve, directly specifying |
295 |
* each coordinate value. The flatness is the maximal distance of a |
* each coordinate value. The flatness is the maximal distance of a |
320 |
return Math.sqrt(getFlatnessSq(x1, y1, cx1, cy1, cx2, cy2, x2, y2)); |
return Math.sqrt(getFlatnessSq(x1, y1, cx1, cy1, cx2, cy2, x2, y2)); |
321 |
} |
} |
322 |
|
|
|
|
|
323 |
/** |
/** |
324 |
* Calculates the squared flatness of a cubic curve, specifying the |
* Calculates the squared flatness of a cubic curve, specifying the |
325 |
* coordinate values in an array. The flatness is the maximal |
* coordinate values in an array. The flatness is the maximal |
353 |
*/ |
*/ |
354 |
public static double getFlatnessSq(double[] coords, int offset) |
public static double getFlatnessSq(double[] coords, int offset) |
355 |
{ |
{ |
356 |
return getFlatnessSq(coords[offset++], coords[offset++], |
return getFlatnessSq(coords[offset++], coords[offset++], coords[offset++], |
357 |
coords[offset++], coords[offset++], |
coords[offset++], coords[offset++], coords[offset++], |
|
coords[offset++], coords[offset++], |
|
358 |
coords[offset++], coords[offset++]); |
coords[offset++], coords[offset++]); |
359 |
} |
} |
360 |
|
|
|
|
|
361 |
/** |
/** |
362 |
* Calculates the flatness of a cubic curve, specifying the |
* Calculates the flatness of a cubic curve, specifying the |
363 |
* coordinate values in an array. The flatness is the maximal |
* coordinate values in an array. The flatness is the maximal |
397 |
coords[offset++], coords[offset++])); |
coords[offset++], coords[offset++])); |
398 |
} |
} |
399 |
|
|
|
|
|
400 |
/** |
/** |
401 |
* Calculates the squared flatness of this curve. The flatness is |
* Calculates the squared flatness of this curve. The flatness is |
402 |
* the maximal distance of a control point to the line between start |
* the maximal distance of a control point to the line between start |
417 |
getCtrlX2(), getCtrlY2(), getX2(), getY2()); |
getCtrlX2(), getCtrlY2(), getX2(), getY2()); |
418 |
} |
} |
419 |
|
|
|
|
|
420 |
/** |
/** |
421 |
* Calculates the flatness of this curve. The flatness is the |
* Calculates the flatness of this curve. The flatness is the |
422 |
* maximal distance of a control point to the line between start and |
* maximal distance of a control point to the line between start and |
433 |
*/ |
*/ |
434 |
public double getFlatness() |
public double getFlatness() |
435 |
{ |
{ |
436 |
return Math.sqrt(getFlatnessSq(getX1(), getY1(), getCtrlX1(), |
return Math.sqrt(getFlatnessSq(getX1(), getY1(), getCtrlX1(), getCtrlY1(), |
437 |
getCtrlY1(), getCtrlX2(), getCtrlY2(), |
getCtrlX2(), getCtrlY2(), getX2(), getY2())); |
|
getX2(), getY2())); |
|
438 |
} |
} |
439 |
|
|
|
|
|
440 |
/** |
/** |
441 |
* Subdivides this curve into two halves. |
* Subdivides this curve into two halves. |
442 |
* |
* |
455 |
public void subdivide(CubicCurve2D left, CubicCurve2D right) |
public void subdivide(CubicCurve2D left, CubicCurve2D right) |
456 |
{ |
{ |
457 |
// Use empty slots at end to share single array. |
// Use empty slots at end to share single array. |
458 |
double[] d = new double[] { getX1(), getY1(), getCtrlX1(), getCtrlY1(), |
double[] d = new double[] |
459 |
getCtrlX2(), getCtrlY2(), getX2(), getY2(), |
{ |
460 |
0, 0, 0, 0, 0, 0 }; |
getX1(), getY1(), getCtrlX1(), getCtrlY1(), getCtrlX2(), |
461 |
|
getCtrlY2(), getX2(), getY2(), 0, 0, 0, 0, 0, 0 |
462 |
|
}; |
463 |
subdivide(d, 0, d, 0, d, 6); |
subdivide(d, 0, d, 0, d, 6); |
464 |
if (left != null) |
if (left != null) |
465 |
left.setCurve(d, 0); |
left.setCurve(d, 0); |
467 |
right.setCurve(d, 6); |
right.setCurve(d, 6); |
468 |
} |
} |
469 |
|
|
|
|
|
470 |
/** |
/** |
471 |
* Subdivides a cubic curve into two halves. |
* Subdivides a cubic curve into two halves. |
472 |
* |
* |
484 |
* of <code>src</code>, or <code>null</code> if the caller is not |
* of <code>src</code>, or <code>null</code> if the caller is not |
485 |
* interested in the right half. |
* interested in the right half. |
486 |
*/ |
*/ |
487 |
public static void subdivide(CubicCurve2D src, |
public static void subdivide(CubicCurve2D src, CubicCurve2D left, |
488 |
CubicCurve2D left, CubicCurve2D right) |
CubicCurve2D right) |
489 |
{ |
{ |
490 |
src.subdivide(left, right); |
src.subdivide(left, right); |
491 |
} |
} |
492 |
|
|
|
|
|
493 |
/** |
/** |
494 |
* Subdivides a cubic curve into two halves, passing all coordinates |
* Subdivides a cubic curve into two halves, passing all coordinates |
495 |
* in an array. |
* in an array. |
536 |
* index where the start point’s <i>x</i> coordinate will be |
* index where the start point’s <i>x</i> coordinate will be |
537 |
* stored. |
* stored. |
538 |
*/ |
*/ |
539 |
public static void subdivide(double[] src, int srcOff, |
public static void subdivide(double[] src, int srcOff, double[] left, |
540 |
double[] left, int leftOff, |
int leftOff, double[] right, int rightOff) |
|
double[] right, int rightOff) |
|
541 |
{ |
{ |
542 |
// To understand this code, please have a look at the image |
// To understand this code, please have a look at the image |
543 |
// "CubicCurve2D-3.png" in the sub-directory "doc-files". |
// "CubicCurve2D-3.png" in the sub-directory "doc-files". |
544 |
double src_C1_x, src_C1_y, src_C2_x, src_C2_y; |
double src_C1_x; |
545 |
double left_P1_x, left_P1_y; |
double src_C1_y; |
546 |
double left_C1_x, left_C1_y, left_C2_x, left_C2_y; |
double src_C2_x; |
547 |
double right_C1_x, right_C1_y, right_C2_x, right_C2_y; |
double src_C2_y; |
548 |
double right_P2_x, right_P2_y; |
double left_P1_x; |
549 |
double Mid_x, Mid_y; // Mid = left.P2 = right.P1 |
double left_P1_y; |
550 |
|
double left_C1_x; |
551 |
|
double left_C1_y; |
552 |
|
double left_C2_x; |
553 |
|
double left_C2_y; |
554 |
|
double right_C1_x; |
555 |
|
double right_C1_y; |
556 |
|
double right_C2_x; |
557 |
|
double right_C2_y; |
558 |
|
double right_P2_x; |
559 |
|
double right_P2_y; |
560 |
|
double Mid_x; // Mid = left.P2 = right.P1 |
561 |
|
double Mid_y; // Mid = left.P2 = right.P1 |
562 |
|
|
563 |
left_P1_x = src[srcOff]; |
left_P1_x = src[srcOff]; |
564 |
left_P1_y = src[srcOff + 1]; |
left_P1_y = src[srcOff + 1]; |
583 |
Mid_y = (left_C2_y + right_C1_y) / 2; |
Mid_y = (left_C2_y + right_C1_y) / 2; |
584 |
|
|
585 |
if (left != null) |
if (left != null) |
586 |
{ |
{ |
587 |
left[leftOff] = left_P1_x; |
left[leftOff] = left_P1_x; |
588 |
left[leftOff + 1] = left_P1_y; |
left[leftOff + 1] = left_P1_y; |
589 |
left[leftOff + 2] = left_C1_x; |
left[leftOff + 2] = left_C1_x; |
590 |
left[leftOff + 3] = left_C1_y; |
left[leftOff + 3] = left_C1_y; |
591 |
left[leftOff + 4] = left_C2_x; |
left[leftOff + 4] = left_C2_x; |
592 |
left[leftOff + 5] = left_C2_y; |
left[leftOff + 5] = left_C2_y; |
593 |
left[leftOff + 6] = Mid_x; |
left[leftOff + 6] = Mid_x; |
594 |
left[leftOff + 7] = Mid_y; |
left[leftOff + 7] = Mid_y; |
595 |
} |
} |
596 |
|
|
597 |
if (right != null) |
if (right != null) |
598 |
{ |
{ |
599 |
right[rightOff] = Mid_x; |
right[rightOff] = Mid_x; |
600 |
right[rightOff + 1] = Mid_y; |
right[rightOff + 1] = Mid_y; |
601 |
right[rightOff + 2] = right_C1_x; |
right[rightOff + 2] = right_C1_x; |
602 |
right[rightOff + 3] = right_C1_y; |
right[rightOff + 3] = right_C1_y; |
603 |
right[rightOff + 4] = right_C2_x; |
right[rightOff + 4] = right_C2_x; |
604 |
right[rightOff + 5] = right_C2_y; |
right[rightOff + 5] = right_C2_y; |
605 |
right[rightOff + 6] = right_P2_x; |
right[rightOff + 6] = right_P2_x; |
606 |
right[rightOff + 7] = right_P2_y; |
right[rightOff + 7] = right_P2_y; |
607 |
} |
} |
608 |
} |
} |
609 |
|
|
|
|
|
610 |
/** |
/** |
611 |
* Finds the non-complex roots of a cubic equation, placing the |
* Finds the non-complex roots of a cubic equation, placing the |
612 |
* results into the same array as the equation coefficients. The |
* results into the same array as the equation coefficients. The |
653 |
return solveCubic(eqn, eqn); |
return solveCubic(eqn, eqn); |
654 |
} |
} |
655 |
|
|
|
|
|
656 |
/** |
/** |
657 |
* Finds the non-complex roots of a cubic equation. The following |
* Finds the non-complex roots of a cubic equation. The following |
658 |
* equation is being solved: |
* equation is being solved: |
709 |
// The Java implementation is very similar to the GSL code, but |
// The Java implementation is very similar to the GSL code, but |
710 |
// not a strict one-to-one copy. For example, GSL would sort the |
// not a strict one-to-one copy. For example, GSL would sort the |
711 |
// result. |
// result. |
712 |
|
double a; |
713 |
|
|
714 |
|
// Adapted from poly/solve_cubic.c in the GNU Scientific Library |
715 |
|
// (GSL), revision 1.7 of 2003-07-26. For the original source, see |
716 |
|
// http://www.gnu.org/software/gsl/ |
717 |
|
// |
718 |
|
// Brian Gough, the author of that code, has granted the |
719 |
|
// permission to use it in GNU Classpath under the GNU Classpath |
720 |
|
// license, and has assigned the copyright to the Free Software |
721 |
|
// Foundation. |
722 |
|
// |
723 |
|
// The Java implementation is very similar to the GSL code, but |
724 |
|
// not a strict one-to-one copy. For example, GSL would sort the |
725 |
|
// result. |
726 |
|
double b; |
727 |
|
|
728 |
|
// Adapted from poly/solve_cubic.c in the GNU Scientific Library |
729 |
|
// (GSL), revision 1.7 of 2003-07-26. For the original source, see |
730 |
|
// http://www.gnu.org/software/gsl/ |
731 |
|
// |
732 |
|
// Brian Gough, the author of that code, has granted the |
733 |
|
// permission to use it in GNU Classpath under the GNU Classpath |
734 |
|
// license, and has assigned the copyright to the Free Software |
735 |
|
// Foundation. |
736 |
|
// |
737 |
|
// The Java implementation is very similar to the GSL code, but |
738 |
|
// not a strict one-to-one copy. For example, GSL would sort the |
739 |
|
// result. |
740 |
|
double c; |
741 |
|
|
742 |
|
// Adapted from poly/solve_cubic.c in the GNU Scientific Library |
743 |
|
// (GSL), revision 1.7 of 2003-07-26. For the original source, see |
744 |
|
// http://www.gnu.org/software/gsl/ |
745 |
|
// |
746 |
|
// Brian Gough, the author of that code, has granted the |
747 |
|
// permission to use it in GNU Classpath under the GNU Classpath |
748 |
|
// license, and has assigned the copyright to the Free Software |
749 |
|
// Foundation. |
750 |
|
// |
751 |
|
// The Java implementation is very similar to the GSL code, but |
752 |
|
// not a strict one-to-one copy. For example, GSL would sort the |
753 |
|
// result. |
754 |
|
double q; |
755 |
|
|
756 |
double a, b, c, q, r, Q, R; |
// Adapted from poly/solve_cubic.c in the GNU Scientific Library |
757 |
double c3, Q3, R2, CR2, CQ3; |
// (GSL), revision 1.7 of 2003-07-26. For the original source, see |
758 |
|
// http://www.gnu.org/software/gsl/ |
759 |
|
// |
760 |
|
// Brian Gough, the author of that code, has granted the |
761 |
|
// permission to use it in GNU Classpath under the GNU Classpath |
762 |
|
// license, and has assigned the copyright to the Free Software |
763 |
|
// Foundation. |
764 |
|
// |
765 |
|
// The Java implementation is very similar to the GSL code, but |
766 |
|
// not a strict one-to-one copy. For example, GSL would sort the |
767 |
|
// result. |
768 |
|
double r; |
769 |
|
|
770 |
|
// Adapted from poly/solve_cubic.c in the GNU Scientific Library |
771 |
|
// (GSL), revision 1.7 of 2003-07-26. For the original source, see |
772 |
|
// http://www.gnu.org/software/gsl/ |
773 |
|
// |
774 |
|
// Brian Gough, the author of that code, has granted the |
775 |
|
// permission to use it in GNU Classpath under the GNU Classpath |
776 |
|
// license, and has assigned the copyright to the Free Software |
777 |
|
// Foundation. |
778 |
|
// |
779 |
|
// The Java implementation is very similar to the GSL code, but |
780 |
|
// not a strict one-to-one copy. For example, GSL would sort the |
781 |
|
// result. |
782 |
|
double Q; |
783 |
|
|
784 |
|
// Adapted from poly/solve_cubic.c in the GNU Scientific Library |
785 |
|
// (GSL), revision 1.7 of 2003-07-26. For the original source, see |
786 |
|
// http://www.gnu.org/software/gsl/ |
787 |
|
// |
788 |
|
// Brian Gough, the author of that code, has granted the |
789 |
|
// permission to use it in GNU Classpath under the GNU Classpath |
790 |
|
// license, and has assigned the copyright to the Free Software |
791 |
|
// Foundation. |
792 |
|
// |
793 |
|
// The Java implementation is very similar to the GSL code, but |
794 |
|
// not a strict one-to-one copy. For example, GSL would sort the |
795 |
|
// result. |
796 |
|
double R; |
797 |
|
double c3; |
798 |
|
double Q3; |
799 |
|
double R2; |
800 |
|
double CR2; |
801 |
|
double CQ3; |
802 |
|
|
803 |
// If the cubic coefficient is zero, we have a quadratic equation. |
// If the cubic coefficient is zero, we have a quadratic equation. |
804 |
c3 = eqn[3]; |
c3 = eqn[3]; |
824 |
CQ3 = 2916 * q * q * q; |
CQ3 = 2916 * q * q * q; |
825 |
|
|
826 |
if (R == 0 && Q == 0) |
if (R == 0 && Q == 0) |
|
{ |
|
|
// The GNU Scientific Library would return three identical |
|
|
// solutions in this case. |
|
|
res[0] = -a/3; |
|
|
return 1; |
|
|
} |
|
|
|
|
|
if (CR2 == CQ3) |
|
|
{ |
|
|
/* this test is actually R2 == Q3, written in a form suitable |
|
|
for exact computation with integers */ |
|
|
|
|
|
/* Due to finite precision some double roots may be missed, and |
|
|
considered to be a pair of complex roots z = x +/- epsilon i |
|
|
close to the real axis. */ |
|
|
|
|
|
double sqrtQ = Math.sqrt(Q); |
|
|
|
|
|
if (R > 0) |
|
827 |
{ |
{ |
828 |
res[0] = -2 * sqrtQ - a/3; |
// The GNU Scientific Library would return three identical |
829 |
res[1] = sqrtQ - a/3; |
// solutions in this case. |
830 |
|
res[0] = -a / 3; |
831 |
|
return 1; |
832 |
} |
} |
833 |
else |
|
834 |
|
if (CR2 == CQ3) |
835 |
{ |
{ |
836 |
res[0] = -sqrtQ - a/3; |
/* this test is actually R2 == Q3, written in a form suitable |
837 |
res[1] = 2 * sqrtQ - a/3; |
for exact computation with integers */ |
838 |
|
/* Due to finite precision some double roots may be missed, and |
839 |
|
considered to be a pair of complex roots z = x +/- epsilon i |
840 |
|
close to the real axis. */ |
841 |
|
double sqrtQ = Math.sqrt(Q); |
842 |
|
|
843 |
|
if (R > 0) |
844 |
|
{ |
845 |
|
res[0] = -2 * sqrtQ - a / 3; |
846 |
|
res[1] = sqrtQ - a / 3; |
847 |
|
} |
848 |
|
else |
849 |
|
{ |
850 |
|
res[0] = -sqrtQ - a / 3; |
851 |
|
res[1] = 2 * sqrtQ - a / 3; |
852 |
|
} |
853 |
|
return 2; |
854 |
} |
} |
|
return 2; |
|
|
} |
|
855 |
|
|
856 |
if (CR2 < CQ3) /* equivalent to R2 < Q3 */ |
if (CR2 < CQ3) /* equivalent to R2 < Q3 */ |
857 |
{ |
{ |
858 |
double sqrtQ = Math.sqrt(Q); |
double sqrtQ = Math.sqrt(Q); |
859 |
double sqrtQ3 = sqrtQ * sqrtQ * sqrtQ; |
double sqrtQ3 = sqrtQ * sqrtQ * sqrtQ; |
860 |
double theta = Math.acos(R / sqrtQ3); |
double theta = Math.acos(R / sqrtQ3); |
861 |
double norm = -2 * sqrtQ; |
double norm = -2 * sqrtQ; |
862 |
res[0] = norm * Math.cos(theta / 3) - a / 3; |
res[0] = norm * Math.cos(theta / 3) - a / 3; |
863 |
res[1] = norm * Math.cos((theta + 2.0 * Math.PI) / 3) - a/3; |
res[1] = norm * Math.cos((theta + 2.0 * Math.PI) / 3) - a / 3; |
864 |
res[2] = norm * Math.cos((theta - 2.0 * Math.PI) / 3) - a/3; |
res[2] = norm * Math.cos((theta - 2.0 * Math.PI) / 3) - a / 3; |
865 |
|
|
866 |
// The GNU Scientific Library sorts the results. We don't. |
// The GNU Scientific Library sorts the results. We don't. |
867 |
return 3; |
return 3; |
868 |
} |
} |
869 |
|
|
870 |
double sgnR = (R >= 0 ? 1 : -1); |
double sgnR = (R >= 0 ? 1 : -1); |
871 |
double A = -sgnR * Math.pow(Math.abs(R) + Math.sqrt(R2 - Q3), 1.0/3.0); |
double A = -sgnR * Math.pow(Math.abs(R) + Math.sqrt(R2 - Q3), 1.0 / 3.0); |
872 |
double B = Q / A ; |
double B = Q / A; |
873 |
res[0] = A + B - a/3; |
res[0] = A + B - a / 3; |
874 |
return 1; |
return 1; |
875 |
} |
} |
876 |
|
|
|
|
|
877 |
/** |
/** |
878 |
* Determines whether a position lies inside the area that is bounded |
* Determines whether a position lies inside the area bounded |
879 |
* by the curve and the straight line connecting its end points. |
* by the curve and the straight line connecting its end points. |
880 |
* |
* |
881 |
* <p><img src="doc-files/CubicCurve2D-5.png" width="350" height="180" |
* <p><img src="doc-files/CubicCurve2D-5.png" width="350" height="180" |
882 |
* alt="A drawing of the area spanned by the curve" /> |
* alt="A drawing of the area spanned by the curve" /> |
883 |
* |
* |
884 |
* <p>The above drawing illustrates in which area points are |
* <p>The above drawing illustrates in which area points are |
885 |
* considered “contained” in a CubicCurve2D. |
* considered “inside” a CubicCurve2D. |
886 |
*/ |
*/ |
887 |
public boolean contains(double x, double y) |
public boolean contains(double x, double y) |
888 |
{ |
{ |
889 |
// XXX Implement. |
if (! getBounds2D().contains(x, y)) |
890 |
throw new Error("not implemented"); |
return false; |
|
} |
|
891 |
|
|
892 |
|
return ((getAxisIntersections(x, y, true, BIG_VALUE) & 1) != 0); |
893 |
|
} |
894 |
|
|
895 |
/** |
/** |
896 |
* Determines whether a point lies inside the area that is bounded |
* Determines whether a point lies inside the area bounded |
897 |
* by the curve and the straight line connecting its end points. |
* by the curve and the straight line connecting its end points. |
898 |
* |
* |
899 |
* <p><img src="doc-files/CubicCurve2D-5.png" width="350" height="180" |
* <p><img src="doc-files/CubicCurve2D-5.png" width="350" height="180" |
900 |
* alt="A drawing of the area spanned by the curve" /> |
* alt="A drawing of the area spanned by the curve" /> |
901 |
* |
* |
902 |
* <p>The above drawing illustrates in which area points are |
* <p>The above drawing illustrates in which area points are |
903 |
* considered “contained” in a CubicCurve2D. |
* considered “inside” a CubicCurve2D. |
904 |
*/ |
*/ |
905 |
public boolean contains(Point2D p) |
public boolean contains(Point2D p) |
906 |
{ |
{ |
907 |
return contains(p.getX(), p.getY()); |
return contains(p.getX(), p.getY()); |
908 |
} |
} |
909 |
|
|
910 |
|
/** |
911 |
|
* Determines whether any part of a rectangle is inside the area bounded |
912 |
|
* by the curve and the straight line connecting its end points. |
913 |
|
* |
914 |
|
* <p><img src="doc-files/CubicCurve2D-5.png" width="350" height="180" |
915 |
|
* alt="A drawing of the area spanned by the curve" /> |
916 |
|
* |
917 |
|
* <p>The above drawing illustrates in which area points are |
918 |
|
* considered “inside” in a CubicCurve2D. |
919 |
|
* @see #contains(double, double) |
920 |
|
*/ |
921 |
public boolean intersects(double x, double y, double w, double h) |
public boolean intersects(double x, double y, double w, double h) |
922 |
{ |
{ |
923 |
// XXX Implement. |
if (! getBounds2D().contains(x, y, w, h)) |
924 |
throw new Error("not implemented"); |
return false; |
925 |
} |
|
926 |
|
/* Does any edge intersect? */ |
927 |
|
if (getAxisIntersections(x, y, true, w) != 0 /* top */ |
928 |
|
|| getAxisIntersections(x, y + h, true, w) != 0 /* bottom */ |
929 |
|
|| getAxisIntersections(x + w, y, false, h) != 0 /* right */ |
930 |
|
|| getAxisIntersections(x, y, false, h) != 0) /* left */ |
931 |
|
return true; |
932 |
|
|
933 |
|
/* No intersections, is any point inside? */ |
934 |
|
if ((getAxisIntersections(x, y, true, BIG_VALUE) & 1) != 0) |
935 |
|
return true; |
936 |
|
|
937 |
|
return false; |
938 |
|
} |
939 |
|
|
940 |
|
/** |
941 |
|
* Determines whether any part of a Rectangle2D is inside the area bounded |
942 |
|
* by the curve and the straight line connecting its end points. |
943 |
|
* @see #intersects(double, double, double, double) |
944 |
|
*/ |
945 |
public boolean intersects(Rectangle2D r) |
public boolean intersects(Rectangle2D r) |
946 |
{ |
{ |
947 |
return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight()); |
return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight()); |
948 |
} |
} |
949 |
|
|
950 |
|
/** |
951 |
|
* Determine whether a rectangle is entirely inside the area that is bounded |
952 |
|
* by the curve and the straight line connecting its end points. |
953 |
|
* |
954 |
|
* <p><img src="doc-files/CubicCurve2D-5.png" width="350" height="180" |
955 |
|
* alt="A drawing of the area spanned by the curve" /> |
956 |
|
* |
957 |
|
* <p>The above drawing illustrates in which area points are |
958 |
|
* considered “inside” a CubicCurve2D. |
959 |
|
* @see #contains(double, double) |
960 |
|
*/ |
961 |
public boolean contains(double x, double y, double w, double h) |
public boolean contains(double x, double y, double w, double h) |
962 |
{ |
{ |
963 |
// XXX Implement. |
if (! getBounds2D().intersects(x, y, w, h)) |
964 |
throw new Error("not implemented"); |
return false; |
965 |
} |
|
966 |
|
/* Does any edge intersect? */ |
967 |
|
if (getAxisIntersections(x, y, true, w) != 0 /* top */ |
968 |
|
|| getAxisIntersections(x, y + h, true, w) != 0 /* bottom */ |
969 |
|
|| getAxisIntersections(x + w, y, false, h) != 0 /* right */ |
970 |
|
|| getAxisIntersections(x, y, false, h) != 0) /* left */ |
971 |
|
return false; |
972 |
|
|
973 |
|
/* No intersections, is any point inside? */ |
974 |
|
if ((getAxisIntersections(x, y, true, BIG_VALUE) & 1) != 0) |
975 |
|
return true; |
976 |
|
|
977 |
|
return false; |
978 |
|
} |
979 |
|
|
980 |
|
/** |
981 |
|
* Determine whether a Rectangle2D is entirely inside the area that is |
982 |
|
* bounded by the curve and the straight line connecting its end points. |
983 |
|
* |
984 |
|
* <p><img src="doc-files/CubicCurve2D-5.png" width="350" height="180" |
985 |
|
* alt="A drawing of the area spanned by the curve" /> |
986 |
|
* |
987 |
|
* <p>The above drawing illustrates in which area points are |
988 |
|
* considered “inside” a CubicCurve2D. |
989 |
|
* @see #contains(double, double) |
990 |
|
*/ |
991 |
public boolean contains(Rectangle2D r) |
public boolean contains(Rectangle2D r) |
992 |
{ |
{ |
993 |
return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight()); |
return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight()); |
994 |
} |
} |
995 |
|
|
|
|
|
996 |
/** |
/** |
997 |
* Determines the smallest rectangle that encloses the |
* Determines the smallest rectangle that encloses the |
998 |
* curve’s start, end and control points. As the illustration |
* curve’s start, end and control points. |
|
* below shows, the invisible control points may cause the bounds to |
|
|
* be much larger than the area that is actually covered by the |
|
|
* curve. |
|
|
* |
|
|
* <p><img src="doc-files/CubicCurve2D-2.png" width="350" height="180" |
|
|
* alt="An illustration of the bounds of a CubicCurve2D" /> |
|
999 |
*/ |
*/ |
1000 |
public Rectangle getBounds() |
public Rectangle getBounds() |
1001 |
{ |
{ |
1002 |
return getBounds2D().getBounds(); |
return getBounds2D().getBounds(); |
1003 |
} |
} |
1004 |
|
|
|
|
|
1005 |
public PathIterator getPathIterator(final AffineTransform at) |
public PathIterator getPathIterator(final AffineTransform at) |
1006 |
{ |
{ |
1007 |
return new PathIterator() |
return new PathIterator() |
|
{ |
|
|
/** Current coordinate. */ |
|
|
private int current = 0; |
|
|
|
|
|
public int getWindingRule() |
|
|
{ |
|
|
return WIND_NON_ZERO; |
|
|
} |
|
|
|
|
|
public boolean isDone() |
|
|
{ |
|
|
return current >= 2; |
|
|
} |
|
|
|
|
|
public void next() |
|
|
{ |
|
|
current++; |
|
|
} |
|
|
|
|
|
public int currentSegment(float[] coords) |
|
1008 |
{ |
{ |
1009 |
int result; |
/** Current coordinate. */ |
1010 |
switch (current) |
private int current = 0; |
|
{ |
|
|
case 0: |
|
|
coords[0] = (float) getX1(); |
|
|
coords[1] = (float) getY1(); |
|
|
result = SEG_MOVETO; |
|
|
break; |
|
|
case 1: |
|
|
coords[0] = (float) getCtrlX1(); |
|
|
coords[1] = (float) getCtrlY1(); |
|
|
coords[2] = (float) getCtrlX2(); |
|
|
coords[3] = (float) getCtrlY2(); |
|
|
coords[4] = (float) getX2(); |
|
|
coords[5] = (float) getY2(); |
|
|
result = SEG_CUBICTO; |
|
|
break; |
|
|
default: |
|
|
throw new NoSuchElementException("cubic iterator out of bounds"); |
|
|
} |
|
|
if (at != null) |
|
|
at.transform(coords, 0, coords, 0, 3); |
|
|
return result; |
|
|
} |
|
1011 |
|
|
1012 |
public int currentSegment(double[] coords) |
public int getWindingRule() |
1013 |
{ |
{ |
1014 |
int result; |
return WIND_NON_ZERO; |
1015 |
switch (current) |
} |
1016 |
{ |
|
1017 |
case 0: |
public boolean isDone() |
1018 |
coords[0] = getX1(); |
{ |
1019 |
coords[1] = getY1(); |
return current >= 2; |
1020 |
result = SEG_MOVETO; |
} |
1021 |
break; |
|
1022 |
case 1: |
public void next() |
1023 |
coords[0] = getCtrlX1(); |
{ |
1024 |
coords[1] = getCtrlY1(); |
current++; |
1025 |
coords[2] = getCtrlX2(); |
} |
1026 |
coords[3] = getCtrlY2(); |
|
1027 |
coords[4] = getX2(); |
public int currentSegment(float[] coords) |
1028 |
coords[5] = getY2(); |
{ |
1029 |
result = SEG_CUBICTO; |
int result; |
1030 |
break; |
switch (current) |
1031 |
default: |
{ |
1032 |
throw new NoSuchElementException("cubic iterator out of bounds"); |
case 0: |
1033 |
} |
coords[0] = (float) getX1(); |
1034 |
if (at != null) |
coords[1] = (float) getY1(); |
1035 |
at.transform(coords, 0, coords, 0, 3); |
result = SEG_MOVETO; |
1036 |
return result; |
break; |
1037 |
} |
case 1: |
1038 |
}; |
coords[0] = (float) getCtrlX1(); |
1039 |
|
coords[1] = (float) getCtrlY1(); |
1040 |
|
coords[2] = (float) getCtrlX2(); |
1041 |
|
coords[3] = (float) getCtrlY2(); |
1042 |
|
coords[4] = (float) getX2(); |
1043 |
|
coords[5] = (float) getY2(); |
1044 |
|
result = SEG_CUBICTO; |
1045 |
|
break; |
1046 |
|
default: |
1047 |
|
throw new NoSuchElementException("cubic iterator out of bounds"); |
1048 |
|
} |
1049 |
|
if (at != null) |
1050 |
|
at.transform(coords, 0, coords, 0, 3); |
1051 |
|
return result; |
1052 |
|
} |
1053 |
|
|
1054 |
|
public int currentSegment(double[] coords) |
1055 |
|
{ |
1056 |
|
int result; |
1057 |
|
switch (current) |
1058 |
|
{ |
1059 |
|
case 0: |
1060 |
|
coords[0] = getX1(); |
1061 |
|
coords[1] = getY1(); |
1062 |
|
result = SEG_MOVETO; |
1063 |
|
break; |
1064 |
|
case 1: |
1065 |
|
coords[0] = getCtrlX1(); |
1066 |
|
coords[1] = getCtrlY1(); |
1067 |
|
coords[2] = getCtrlX2(); |
1068 |
|
coords[3] = getCtrlY2(); |
1069 |
|
coords[4] = getX2(); |
1070 |
|
coords[5] = getY2(); |
1071 |
|
result = SEG_CUBICTO; |
1072 |
|
break; |
1073 |
|
default: |
1074 |
|
throw new NoSuchElementException("cubic iterator out of bounds"); |
1075 |
|
} |
1076 |
|
if (at != null) |
1077 |
|
at.transform(coords, 0, coords, 0, 3); |
1078 |
|
return result; |
1079 |
|
} |
1080 |
|
}; |
1081 |
} |
} |
1082 |
|
|
|
|
|
1083 |
public PathIterator getPathIterator(AffineTransform at, double flatness) |
public PathIterator getPathIterator(AffineTransform at, double flatness) |
1084 |
{ |
{ |
1085 |
return new FlatteningPathIterator(getPathIterator(at), flatness); |
return new FlatteningPathIterator(getPathIterator(at), flatness); |
1086 |
} |
} |
1087 |
|
|
|
|
|
1088 |
/** |
/** |
1089 |
* Create a new curve with the same contents as this one. |
* Create a new curve with the same contents as this one. |
1090 |
* |
* |
1093 |
public Object clone() |
public Object clone() |
1094 |
{ |
{ |
1095 |
try |
try |
1096 |
{ |
{ |
1097 |
return super.clone(); |
return super.clone(); |
1098 |
} |
} |
1099 |
catch (CloneNotSupportedException e) |
catch (CloneNotSupportedException e) |
1100 |
{ |
{ |
1101 |
throw (Error) new InternalError().initCause(e); // Impossible |
throw (Error) new InternalError().initCause(e); // Impossible |
1102 |
} |
} |
1103 |
} |
} |
1104 |
|
|
1105 |
|
/** |
1106 |
|
* Helper method used by contains() and intersects() methods, that |
1107 |
|
* returns the number of curve/line intersections on a given axis |
1108 |
|
* extending from a certain point. |
1109 |
|
* |
1110 |
|
* @param x x coordinate of the origin point |
1111 |
|
* @param y y coordinate of the origin point |
1112 |
|
* @param useYaxis axis used, if true the positive Y axis is used, |
1113 |
|
* false uses the positive X axis. |
1114 |
|
* |
1115 |
|
* This is an implementation of the line-crossings algorithm, |
1116 |
|
* Detailed in an article on Eric Haines' page: |
1117 |
|
* http://www.acm.org/tog/editors/erich/ptinpoly/ |
1118 |
|
* |
1119 |
|
* A special-case not adressed in this code is self-intersections |
1120 |
|
* of the curve, e.g. if the axis intersects the self-itersection, |
1121 |
|
* the degenerate roots of the polynomial will erroneously count as |
1122 |
|
* a single intersection of the curve, and not two. |
1123 |
|
*/ |
1124 |
|
private int getAxisIntersections(double x, double y, boolean useYaxis, |
1125 |
|
double distance) |
1126 |
|
{ |
1127 |
|
int nCrossings = 0; |
1128 |
|
double a0; |
1129 |
|
double a1; |
1130 |
|
double a2; |
1131 |
|
double a3; |
1132 |
|
double b0; |
1133 |
|
double b1; |
1134 |
|
double b2; |
1135 |
|
double b3; |
1136 |
|
double[] r = new double[4]; |
1137 |
|
int nRoots; |
1138 |
|
|
1139 |
|
a0 = a3 = 0.0; |
1140 |
|
|
1141 |
|
if (useYaxis) |
1142 |
|
{ |
1143 |
|
a0 = getY1() - y; |
1144 |
|
a1 = getCtrlY1() - y; |
1145 |
|
a2 = getCtrlY2() - y; |
1146 |
|
a3 = getY2() - y; |
1147 |
|
b0 = getX1() - x; |
1148 |
|
b1 = getCtrlX1() - x; |
1149 |
|
b2 = getCtrlX2() - x; |
1150 |
|
b3 = getX2() - x; |
1151 |
|
} |
1152 |
|
else |
1153 |
|
{ |
1154 |
|
a0 = getX1() - x; |
1155 |
|
a1 = getCtrlX1() - x; |
1156 |
|
a2 = getCtrlX2() - x; |
1157 |
|
a3 = getX2() - x; |
1158 |
|
b0 = getY1() - y; |
1159 |
|
b1 = getCtrlY1() - y; |
1160 |
|
b2 = getCtrlY2() - y; |
1161 |
|
b3 = getY2() - y; |
1162 |
|
} |
1163 |
|
|
1164 |
|
/* If the axis intersects a start/endpoint, shift it up by some small |
1165 |
|
amount to guarantee the line is 'inside' |
1166 |
|
If this is not done, bad behaviour may result for points on that axis.*/ |
1167 |
|
if (a0 == 0.0 || a3 == 0.0) |
1168 |
|
{ |
1169 |
|
double small = getFlatness() * (1E-10); |
1170 |
|
if (a0 == 0.0) |
1171 |
|
a0 += small; |
1172 |
|
if (a3 == 0.0) |
1173 |
|
a3 += small; |
1174 |
|
} |
1175 |
|
|
1176 |
|
if (useYaxis) |
1177 |
|
{ |
1178 |
|
if (Line2D.linesIntersect(b0, a0, b3, a3, 0.0, 0.0, distance, 0.0)) |
1179 |
|
nCrossings++; |
1180 |
|
} |
1181 |
|
else |
1182 |
|
{ |
1183 |
|
if (Line2D.linesIntersect(a0, b0, a3, b3, 0.0, 0.0, 0.0, distance)) |
1184 |
|
nCrossings++; |
1185 |
|
} |
1186 |
|
|
1187 |
|
r[0] = a0; |
1188 |
|
r[1] = 3 * (a1 - a0); |
1189 |
|
r[2] = 3 * (a2 + a0 - 2 * a1); |
1190 |
|
r[3] = a3 - 3 * a2 + 3 * a1 - a0; |
1191 |
|
|
1192 |
|
if ((nRoots = solveCubic(r)) != 0) |
1193 |
|
for (int i = 0; i < nRoots; i++) |
1194 |
|
{ |
1195 |
|
double t = r[i]; |
1196 |
|
if (t >= 0.0 && t <= 1.0) |
1197 |
|
{ |
1198 |
|
double crossing = -(t * t * t) * (b0 - 3 * b1 + 3 * b2 - b3) |
1199 |
|
+ 3 * t * t * (b0 - 2 * b1 + b2) |
1200 |
|
+ 3 * t * (b1 - b0) + b0; |
1201 |
|
if (crossing > 0.0 && crossing <= distance) |
1202 |
|
nCrossings++; |
1203 |
|
} |
1204 |
|
} |
1205 |
|
|
1206 |
|
return (nCrossings); |
1207 |
|
} |
1208 |
|
|
1209 |
/** |
/** |
1210 |
* A two-dimensional curve that is parameterized with a cubic |
* A two-dimensional curve that is parameterized with a cubic |
1216 |
* @author Eric Blake (ebb9@email.byu.edu) |
* @author Eric Blake (ebb9@email.byu.edu) |
1217 |
* @author Sascha Brawer (brawer@dandelis.ch) |
* @author Sascha Brawer (brawer@dandelis.ch) |
1218 |
*/ |
*/ |
1219 |
public static class Double |
public static class Double extends CubicCurve2D |
|
extends CubicCurve2D |
|
1220 |
{ |
{ |
1221 |
/** |
/** |
1222 |
* The <i>x</i> coordinate of the curve’s start point. |
* The <i>x</i> coordinate of the curve’s start point. |
1223 |
*/ |
*/ |
1224 |
public double x1; |
public double x1; |
1225 |
|
|
|
|
|
1226 |
/** |
/** |
1227 |
* The <i>y</i> coordinate of the curve’s start point. |
* The <i>y</i> coordinate of the curve’s start point. |
1228 |
*/ |
*/ |
1229 |
public double y1; |
public double y1; |
1230 |
|
|
|
|
|
1231 |
/** |
/** |
1232 |
* The <i>x</i> coordinate of the curve’s first control point. |
* The <i>x</i> coordinate of the curve’s first control point. |
1233 |
*/ |
*/ |
1234 |
public double ctrlx1; |
public double ctrlx1; |
1235 |
|
|
|
|
|
1236 |
/** |
/** |
1237 |
* The <i>y</i> coordinate of the curve’s first control point. |
* The <i>y</i> coordinate of the curve’s first control point. |
1238 |
*/ |
*/ |
1239 |
public double ctrly1; |
public double ctrly1; |
1240 |
|
|
|
|
|
1241 |
/** |
/** |
1242 |
* The <i>x</i> coordinate of the curve’s second control point. |
* The <i>x</i> coordinate of the curve’s second control point. |
1243 |
*/ |
*/ |
1244 |
public double ctrlx2; |
public double ctrlx2; |
1245 |
|
|
|
|
|
1246 |
/** |
/** |
1247 |
* The <i>y</i> coordinate of the curve’s second control point. |
* The <i>y</i> coordinate of the curve’s second control point. |
1248 |
*/ |
*/ |
1249 |
public double ctrly2; |
public double ctrly2; |
1250 |
|
|
|
|
|
1251 |
/** |
/** |
1252 |
* The <i>x</i> coordinate of the curve’s end point. |
* The <i>x</i> coordinate of the curve’s end point. |
1253 |
*/ |
*/ |
1254 |
public double x2; |
public double x2; |
1255 |
|
|
|
|
|
1256 |
/** |
/** |
1257 |
* The <i>y</i> coordinate of the curve’s end point. |
* The <i>y</i> coordinate of the curve’s end point. |
1258 |
*/ |
*/ |
1259 |
public double y2; |
public double y2; |
1260 |
|
|
|
|
|
1261 |
/** |
/** |
1262 |
* Constructs a new CubicCurve2D that stores its coordinate values |
* Constructs a new CubicCurve2D that stores its coordinate values |
1263 |
* in double-precision floating-point format. All points are |
* in double-precision floating-point format. All points are |
1267 |
{ |
{ |
1268 |
} |
} |
1269 |
|
|
|
|
|
1270 |
/** |
/** |
1271 |
* Constructs a new CubicCurve2D that stores its coordinate values |
* Constructs a new CubicCurve2D that stores its coordinate values |
1272 |
* in double-precision floating-point format, specifying the |
* in double-precision floating-point format, specifying the |
1299 |
* @param y2 the <i>y</i> coordinate of the curve’s end |
* @param y2 the <i>y</i> coordinate of the curve’s end |
1300 |
* point. |
* point. |
1301 |
*/ |
*/ |
1302 |
public Double(double x1, double y1, double cx1, double cy1, |
public Double(double x1, double y1, double cx1, double cy1, double cx2, |
1303 |
double cx2, double cy2, double x2, double y2) |
double cy2, double x2, double y2) |
1304 |
{ |
{ |
1305 |
this.x1 = x1; |
this.x1 = x1; |
1306 |
this.y1 = y1; |
this.y1 = y1; |
1312 |
this.y2 = y2; |
this.y2 = y2; |
1313 |
} |
} |
1314 |
|
|
|
|
|
1315 |
/** |
/** |
1316 |
* Returns the <i>x</i> coordinate of the curve’s start |
* Returns the <i>x</i> coordinate of the curve’s start |
1317 |
* point. |
* point. |
1321 |
return x1; |
return x1; |
1322 |
} |
} |
1323 |
|
|
|
|
|
1324 |
/** |
/** |
1325 |
* Returns the <i>y</i> coordinate of the curve’s start |
* Returns the <i>y</i> coordinate of the curve’s start |
1326 |
* point. |
* point. |
1330 |
return y1; |
return y1; |
1331 |
} |
} |
1332 |
|
|
|
|
|
1333 |
/** |
/** |
1334 |
* Returns the curve’s start point. |
* Returns the curve’s start point. |
1335 |
*/ |
*/ |
1338 |
return new Point2D.Double(x1, y1); |
return new Point2D.Double(x1, y1); |
1339 |
} |
} |
1340 |
|
|
|
|
|
1341 |
/** |
/** |
1342 |
* Returns the <i>x</i> coordinate of the curve’s first |
* Returns the <i>x</i> coordinate of the curve’s first |
1343 |
* control point. |
* control point. |
1347 |
return ctrlx1; |
return ctrlx1; |
1348 |
} |
} |
1349 |
|
|
|
|
|
1350 |
/** |
/** |
1351 |
* Returns the <i>y</i> coordinate of the curve’s first |
* Returns the <i>y</i> coordinate of the curve’s first |
1352 |
* control point. |
* control point. |
1356 |
return ctrly1; |
return ctrly1; |
1357 |
} |
} |
1358 |
|
|
|
|
|
1359 |
/** |
/** |
1360 |
* Returns the curve’s first control point. |
* Returns the curve’s first control point. |
1361 |
*/ |
*/ |
1364 |
return new Point2D.Double(ctrlx1, ctrly1); |
return new Point2D.Double(ctrlx1, ctrly1); |
1365 |
} |
} |
1366 |
|
|
|
|
|
1367 |
/** |
/** |
1368 |
* Returns the <i>x</i> coordinate of the curve’s second |
* Returns the <i>x</i> coordinate of the curve’s second |
1369 |
* control point. |
* control point. |
1373 |
return ctrlx2; |
return ctrlx2; |
1374 |
} |
} |
1375 |
|
|
|
|
|
1376 |
/** |
/** |
1377 |
* Returns the <i>y</i> coordinate of the curve’s second |
* Returns the <i>y</i> coordinate of the curve’s second |
1378 |
* control point. |
* control point. |
1382 |
return ctrly2; |
return ctrly2; |
1383 |
} |
} |
1384 |
|
|
|
|
|
1385 |
/** |
/** |
1386 |
* Returns the curve’s second control point. |
* Returns the curve’s second control point. |
1387 |
*/ |
*/ |
1390 |
return new Point2D.Double(ctrlx2, ctrly2); |
return new Point2D.Double(ctrlx2, ctrly2); |
1391 |
} |
} |
1392 |
|
|
|
|
|
1393 |
/** |
/** |
1394 |
* Returns the <i>x</i> coordinate of the curve’s end |
* Returns the <i>x</i> coordinate of the curve’s end |
1395 |
* point. |
* point. |
1399 |
return x2; |
return x2; |
1400 |
} |
} |
1401 |
|
|
|
|
|
1402 |
/** |
/** |
1403 |
* Returns the <i>y</i> coordinate of the curve’s end |
* Returns the <i>y</i> coordinate of the curve’s end |
1404 |
* point. |
* point. |
1408 |
return y2; |
return y2; |
1409 |
} |
} |
1410 |
|
|
|
|
|
1411 |
/** |
/** |
1412 |
* Returns the curve’s end point. |
* Returns the curve’s end point. |
1413 |
*/ |
*/ |
1416 |
return new Point2D.Double(x2, y2); |
return new Point2D.Double(x2, y2); |
1417 |
} |
} |
1418 |
|
|
|
|
|
1419 |
/** |
/** |
1420 |
* Changes the curve geometry, separately specifying each coordinate |
* Changes the curve geometry, separately specifying each coordinate |
1421 |
* value. |
* value. |
1460 |
this.y2 = y2; |
this.y2 = y2; |
1461 |
} |
} |
1462 |
|
|
|
|
|
1463 |
/** |
/** |
1464 |
* Determines the smallest rectangle that encloses the |
* Determines the smallest rectangle that encloses the |
1465 |
* curve’s start, end and control points. As the |
* curve’s start, end and control points. As the |
1480 |
} |
} |
1481 |
} |
} |
1482 |
|
|
|
|
|
1483 |
/** |
/** |
1484 |
* A two-dimensional curve that is parameterized with a cubic |
* A two-dimensional curve that is parameterized with a cubic |
1485 |
* function and stores coordinate values in single-precision |
* function and stores coordinate values in single-precision |
1490 |
* @author Eric Blake (ebb9@email.byu.edu) |
* @author Eric Blake (ebb9@email.byu.edu) |
1491 |
* @author Sascha Brawer (brawer@dandelis.ch) |
* @author Sascha Brawer (brawer@dandelis.ch) |
1492 |
*/ |
*/ |
1493 |
public static class Float |
public static class Float extends CubicCurve2D |
|
extends CubicCurve2D |
|
1494 |
{ |
{ |
1495 |
/** |
/** |
1496 |
* The <i>x</i> coordinate of the curve’s start point. |
* The <i>x</i> coordinate of the curve’s start point. |
1497 |
*/ |
*/ |
1498 |
public float x1; |
public float x1; |
1499 |
|
|
|
|
|
1500 |
/** |
/** |
1501 |
* The <i>y</i> coordinate of the curve’s start point. |
* The <i>y</i> coordinate of the curve’s start point. |
1502 |
*/ |
*/ |
1503 |
public float y1; |
public float y1; |
1504 |
|
|
|
|
|
1505 |
/** |
/** |
1506 |
* The <i>x</i> coordinate of the curve’s first control point. |
* The <i>x</i> coordinate of the curve’s first control point. |
1507 |
*/ |
*/ |
1508 |
public float ctrlx1; |
public float ctrlx1; |
1509 |
|
|
|
|
|
1510 |
/** |
/** |
1511 |
* The <i>y</i> coordinate of the curve’s first control point. |
* The <i>y</i> coordinate of the curve’s first control point. |
1512 |
*/ |
*/ |
1513 |
public float ctrly1; |
public float ctrly1; |
1514 |
|
|
|
|
|
1515 |
/** |
/** |
1516 |
* The <i>x</i> coordinate of the curve’s second control point. |
* The <i>x</i> coordinate of the curve’s second control point. |
1517 |
*/ |
*/ |
1518 |
public float ctrlx2; |
public float ctrlx2; |
1519 |
|
|
|
|
|
1520 |
/** |
/** |
1521 |
* The <i>y</i> coordinate of the curve’s second control point. |
* The <i>y</i> coordinate of the curve’s second control point. |
1522 |
*/ |
*/ |
1523 |
public float ctrly2; |
public float ctrly2; |
1524 |
|
|
|
|
|
1525 |
/** |
/** |
1526 |
* The <i>x</i> coordinate of the curve’s end point. |
* The <i>x</i> coordinate of the curve’s end point. |
1527 |
*/ |
*/ |
1528 |
public float x2; |
public float x2; |
1529 |
|
|
|
|
|
1530 |
/** |
/** |
1531 |
* The <i>y</i> coordinate of the curve’s end point. |
* The <i>y</i> coordinate of the curve’s end point. |
1532 |
*/ |
*/ |
1533 |
public float y2; |
public float y2; |
1534 |
|
|
|
|
|
1535 |
/** |
/** |
1536 |
* Constructs a new CubicCurve2D that stores its coordinate values |
* Constructs a new CubicCurve2D that stores its coordinate values |
1537 |
* in single-precision floating-point format. All points are |
* in single-precision floating-point format. All points are |
1541 |
{ |
{ |
1542 |
} |
} |
1543 |
|
|
|
|
|
1544 |
/** |
/** |
1545 |
* Constructs a new CubicCurve2D that stores its coordinate values |
* Constructs a new CubicCurve2D that stores its coordinate values |
1546 |
* in single-precision floating-point format, specifying the |
* in single-precision floating-point format, specifying the |
1573 |
* @param y2 the <i>y</i> coordinate of the curve’s end |
* @param y2 the <i>y</i> coordinate of the curve’s end |
1574 |
* point. |
* point. |
1575 |
*/ |
*/ |
1576 |
public Float(float x1, float y1, float cx1, float cy1, |
public Float(float x1, float y1, float cx1, float cy1, float cx2, |
1577 |
float cx2, float cy2, float x2, float y2) |
float cy2, float x2, float y2) |
1578 |
{ |
{ |
1579 |
this.x1 = x1; |
this.x1 = x1; |
1580 |
this.y1 = y1; |
this.y1 = y1; |
1586 |
this.y2 = y2; |
this.y2 = y2; |
1587 |
} |
} |
1588 |
|
|
|
|
|
1589 |
/** |
/** |
1590 |
* Returns the <i>x</i> coordinate of the curve’s start |
* Returns the <i>x</i> coordinate of the curve’s start |
1591 |
* point. |
* point. |
1595 |
return x1; |
return x1; |
1596 |
} |
} |
1597 |
|
|
|
|
|
1598 |
/** |
/** |
1599 |
* Returns the <i>y</i> coordinate of the curve’s start |
* Returns the <i>y</i> coordinate of the curve’s start |
1600 |
* point. |
* point. |
1604 |
return y1; |
return y1; |
1605 |
} |
} |
1606 |
|
|
|
|
|
1607 |
/** |
/** |
1608 |
* Returns the curve’s start point. |
* Returns the curve’s start point. |
1609 |
*/ |
*/ |
1612 |
return new Point2D.Float(x1, y1); |
return new Point2D.Float(x1, y1); |
1613 |
} |
} |
1614 |
|
|
|
|
|
1615 |
/** |
/** |
1616 |
* Returns the <i>x</i> coordinate of the curve’s first |
* Returns the <i>x</i> coordinate of the curve’s first |
1617 |
* control point. |
* control point. |
1621 |
return ctrlx1; |
return ctrlx1; |
1622 |
} |
} |
1623 |
|
|
|
|
|
1624 |
/** |
/** |
1625 |
* Returns the <i>y</i> coordinate of the curve’s first |
* Returns the <i>y</i> coordinate of the curve’s first |
1626 |
* control point. |
* control point. |
1630 |
return ctrly1; |
return ctrly1; |
1631 |
} |
} |
1632 |
|
|
|
|
|
1633 |
/** |
/** |
1634 |
* Returns the curve’s first control point. |
* Returns the curve’s first control point. |
1635 |
*/ |
*/ |
1638 |
return new Point2D.Float(ctrlx1, ctrly1); |
return new Point2D.Float(ctrlx1, ctrly1); |
1639 |
} |
} |
1640 |
|
|
|
|
|
1641 |
/** |
/** |
1642 |
* Returns the <i>s</i> coordinate of the curve’s second |
* Returns the <i>s</i> coordinate of the curve’s second |
1643 |
* control point. |
* control point. |
1647 |
return ctrlx2; |
return ctrlx2; |
1648 |
} |
} |
1649 |
|
|
|
|
|
1650 |
/** |
/** |
1651 |
* Returns the <i>y</i> coordinate of the curve’s second |
* Returns the <i>y</i> coordinate of the curve’s second |
1652 |
* control point. |
* control point. |
1656 |
return ctrly2; |
return ctrly2; |
1657 |
} |
} |
1658 |
|
|
|
|
|
1659 |
/** |
/** |
1660 |
* Returns the curve’s second control point. |
* Returns the curve’s second control point. |
1661 |
*/ |
*/ |
1664 |
return new Point2D.Float(ctrlx2, ctrly2); |
return new Point2D.Float(ctrlx2, ctrly2); |
1665 |
} |
} |
1666 |
|
|
|
|
|
1667 |
/** |
/** |
1668 |
* Returns the <i>x</i> coordinate of the curve’s end |
* Returns the <i>x</i> coordinate of the curve’s end |
1669 |
* point. |
* point. |
1673 |
return x2; |
return x2; |
1674 |
} |
} |
1675 |
|
|
|
|
|
1676 |
/** |
/** |
1677 |
* Returns the <i>y</i> coordinate of the curve’s end |
* Returns the <i>y</i> coordinate of the curve’s end |
1678 |
* point. |
* point. |
1682 |
return y2; |
return y2; |
1683 |
} |
} |
1684 |
|
|
|
|
|
1685 |
/** |
/** |
1686 |
* Returns the curve’s end point. |
* Returns the curve’s end point. |
1687 |
*/ |
*/ |
1690 |
return new Point2D.Float(x2, y2); |
return new Point2D.Float(x2, y2); |
1691 |
} |
} |
1692 |
|
|
|
|
|
1693 |
/** |
/** |
1694 |
* Changes the curve geometry, separately specifying each coordinate |
* Changes the curve geometry, separately specifying each coordinate |
1695 |
* value as a double-precision floating-point number. |
* value as a double-precision floating-point number. |
1734 |
this.y2 = (float) y2; |
this.y2 = (float) y2; |
1735 |
} |
} |
1736 |
|
|
|
|
|
1737 |
/** |
/** |
1738 |
* Changes the curve geometry, separately specifying each coordinate |
* Changes the curve geometry, separately specifying each coordinate |
1739 |
* value as a single-precision floating-point number. |
* value as a single-precision floating-point number. |
1765 |
* @param y2 the <i>y</i> coordinate of the curve’s new end |
* @param y2 the <i>y</i> coordinate of the curve’s new end |
1766 |
* point. |
* point. |
1767 |
*/ |
*/ |
1768 |
public void setCurve(float x1, float y1, float cx1, float cy1, |
public void setCurve(float x1, float y1, float cx1, float cy1, float cx2, |
1769 |
float cx2, float cy2, float x2, float y2) |
float cy2, float x2, float y2) |
1770 |
{ |
{ |
1771 |
this.x1 = x1; |
this.x1 = x1; |
1772 |
this.y1 = y1; |
this.y1 = y1; |
1778 |
this.y2 = y2; |
this.y2 = y2; |
1779 |
} |
} |
1780 |
|
|
|
|
|
1781 |
/** |
/** |
1782 |
* Determines the smallest rectangle that encloses the |
* Determines the smallest rectangle that encloses the |
1783 |
* curve’s start, end and control points. As the |
* curve’s start, end and control points. As the |