blob: a78aa9f141ec89b2c58817ef278defa4c55f448f [file] [log] [blame]
caryclark@google.com639df892012-01-10 21:46:10 +00001#include "CubicIntersection.h"
2#include "QuadraticUtilities.h"
3
4/* from http://tom.cs.byu.edu/~tom/papers/cvgip84.pdf 4.1
5 *
6 * This paper proves that Syvester's method can compute the implicit form of
7 * the quadratic from the parameterzied form.
8 *
9 * Given x = a*t*t + b*t + c (the parameterized form)
10 * y = d*t*t + e*t + f
11 *
12 * we want to find an equation of the implicit form:
13 *
14 * A*x*x + B*x*y + C*y*y + D*x + E*y + F = 0
15 *
16 * The implicit form can be expressed as a 4x4 determinant, as shown.
17 *
18 * The resultant obtained by Syvester's method is
19 *
20 * | a b (c - x) 0 |
21 * | 0 a b (c - x) |
22 * | d e (f - y) 0 |
23 * | 0 d e (f - y) |
24 *
25 * which expands to
26 *
27 * d*d*x*x + -2*a*d*x*y + a*a*y*y
28 * + (-2*c*d*d + b*e*d - a*e*e + 2*a*f*d)*x
29 * + (-2*f*a*a + e*b*a - d*b*b + 2*d*c*a)*y
30 * +
31 * | a b c 0 |
32 * | 0 a b c | == 0.
33 * | d e f 0 |
34 * | 0 d e f |
35 *
36 * Expanding the constant determinant results in
37 *
38 * | a b c | | b c 0 |
39 * a*| e f 0 | + d*| a b c | ==
40 * | d e f | | d e f |
41 *
42 * a*(a*f*f + c*e*e - c*f*d - b*e*f) + d*(b*b*f + c*c*d - c*a*f - c*e*b)
43 *
44 */
45
46enum {
47 xx_coeff,
48 xy_coeff,
49 yy_coeff,
50 x_coeff,
51 y_coeff,
52 c_coeff,
53 coeff_count
54};
55
56static bool straight_forward = true;
57
58static void implicit_coefficients(const Quadratic& q, double p[coeff_count]) {
59 double a, b, c;
60 set_abc(&q[0].x, a, b, c);
61 double d, e, f;
62 set_abc(&q[0].y, d, e, f);
63 // compute the implicit coefficients
64 if (straight_forward) { // 42 muls, 13 adds
65 p[xx_coeff] = d * d;
66 p[xy_coeff] = -2 * a * d;
67 p[yy_coeff] = a * a;
68 p[x_coeff] = -2*c*d*d + b*e*d - a*e*e + 2*a*f*d;
69 p[y_coeff] = -2*f*a*a + e*b*a - d*b*b + 2*d*c*a;
70 p[c_coeff] = a*(a*f*f + c*e*e - c*f*d - b*e*f)
71 + d*(b*b*f + c*c*d - c*a*f - c*e*b);
72 } else { // 26 muls, 11 adds
73 double aa = a * a;
74 double ad = a * d;
75 double dd = d * d;
76 p[xx_coeff] = dd;
77 p[xy_coeff] = -2 * ad;
78 p[yy_coeff] = aa;
79 double be = b * e;
80 double bde = be * d;
81 double cdd = c * dd;
82 double ee = e * e;
83 p[x_coeff] = -2*cdd + bde - a*ee + 2*ad*f;
84 double aaf = aa * f;
85 double abe = a * be;
86 double ac = a * c;
87 double bb_2ac = b*b - 2*ac;
88 p[y_coeff] = -2*aaf + abe - d*bb_2ac;
89 p[c_coeff] = aaf*f + ac*ee + d*f*bb_2ac - abe*f + c*cdd - c*bde;
90 }
91}
92
93 /* Given a pair of quadratics, determine their parametric coefficients.
94 * If the scaled coefficients are nearly equal, then the part of the quadratics
95 * may be coincident.
96 * FIXME: optimization -- since comparison short-circuits on no match,
97 * lazily compute the coefficients, comparing the easiest to compute first.
98 * xx and yy first; then xy; and so on.
99 */
100bool implicit_matches(const Quadratic& one, const Quadratic& two) {
101 double p1[coeff_count]; // a'xx , b'xy , c'yy , d'x , e'y , f
102 double p2[coeff_count];
103 implicit_coefficients(one, p1);
104 implicit_coefficients(two, p2);
105 int first = 0;
106 for (int index = 0; index < coeff_count; ++index) {
107 if (approximately_zero(p1[index]) || approximately_zero(p2[index])) {
108 first += first == index;
109 continue;
110 }
111 if (first == index) {
112 continue;
113 }
114 if (!approximately_equal(p1[index] * p2[first],
115 p1[first] * p2[index])) {
116 return false;
117 }
118 }
119 return true;
120}
121
122static double tangent(const double* quadratic, double t) {
123 double a, b, c;
124 set_abc(quadratic, a, b, c);
125 return 2 * a * t + b;
126}
127
128void tangent(const Quadratic& quadratic, double t, _Point& result) {
129 result.x = tangent(&quadratic[0].x, t);
130 result.y = tangent(&quadratic[0].y, t);
131}
132