| 148 | } |
| 149 | |
| 150 | static float SolveBezier(float x, float p0, float p1, float p2, float p3) |
| 151 | { |
| 152 | const double x3 = -p0 + 3.0 * p1 - 3.0 * p2 + p3; |
| 153 | const double x2 = 3.0 * p0 - 6.0 * p1 + 3.0 * p2; |
| 154 | const double x1 = -3.0 * p0 + 3.0 * p1; |
| 155 | const double x0 = p0 - x; |
| 156 | |
| 157 | if(x3 == 0.0 && x2 == 0.0) |
| 158 | { |
| 159 | // linear |
| 160 | // a * t + b = 0 |
| 161 | const double a = x1; |
| 162 | const double b = x0; |
| 163 | |
| 164 | if(a == 0.0) |
| 165 | return 0.0f; |
| 166 | return -b / a; |
| 167 | } |
| 168 | else if(x3 == 0.0) |
| 169 | { |
| 170 | // quadratic |
| 171 | // t * t + b * t + c = 0 |
| 172 | const double b = x1 / x2; |
| 173 | const double c = x0 / x2; |
| 174 | |
| 175 | if(c == 0.0) |
| 176 | return 0.0f; |
| 177 | |
| 178 | const double D = b * b - 4.0 * c; |
| 179 | const double SqrtD = std::sqrt(D); |
| 180 | |
| 181 | const double t = (-b + SqrtD) / 2.0; |
| 182 | |
| 183 | if(0.0 <= t && t <= 1.0001) |
| 184 | return t; |
| 185 | return (-b - SqrtD) / 2.0; |
| 186 | } |
| 187 | else |
| 188 | { |
| 189 | // cubic |
| 190 | // t * t * t + a * t * t + b * t * t + c = 0 |
| 191 | const double a = x2 / x3; |
| 192 | const double b = x1 / x3; |
| 193 | const double c = x0 / x3; |
| 194 | |
| 195 | // substitute t = y - a / 3 |
| 196 | const double Substitute = a / 3.0; |
| 197 | |
| 198 | // depressed form x^3 + px + q = 0 |
| 199 | // cardano's method |
| 200 | const double p = b / 3.0 - a * a / 9.0; |
| 201 | const double q = (2.0 * a * a * a / 27.0 - a * b / 3.0 + c) / 2.0; |
| 202 | |
| 203 | const double D = q * q + p * p * p; |
| 204 | |
| 205 | if(D > 0.0) |
| 206 | { |
| 207 | // only one 'real' solution |