X-Git-Url: https://git.ucc.asn.au/?p=ipdf%2Fcode.git;a=blobdiff_plain;f=src%2Fbezier.h;h=9ea730f78c0907a73ecfd5e4b727da5429636417;hp=449d7bde77271204aa2ff0e645fe7bef48f13443;hb=5456793e2aad4235c3db2ca75532c868aaa7c518;hpb=53579b1a949fa3e4e193f8dfba2064edbb123f57 diff --git a/src/bezier.h b/src/bezier.h index 449d7bd..9ea730f 100644 --- a/src/bezier.h +++ b/src/bezier.h @@ -11,11 +11,45 @@ namespace IPDF inline std::pair SolveQuadratic(const Real & a, const Real & b, const Real & c) { - Real x0((b + Sqrt(b*b - Real(4)*a*c))/(Real(2)*a)); - Real x1((b - Sqrt(b*b - Real(4)*a*c))/(Real(2)*a)); + Real x0((-b + Sqrt(b*b - Real(4)*a*c))/(Real(2)*a)); + Real x1((-b - Sqrt(b*b - Real(4)*a*c))/(Real(2)*a)); return std::pair(x0,x1); } + inline std::vector SolveCubic(const Real & a, const Real & b, const Real & c, const Real & d) + { + // This is going to be a big one... + // See http://en.wikipedia.org/wiki/Cubic_function#General_formula_for_roots + + // delta = 18abcd - 4 b^3 d + b^2 c^2 - 4ac^3 - 27 a^2 d^2 + /* + Real discriminant = Real(18) * a * b * c * d - Real(4) * (b * b * b) * d + + (b * b) * (c * c) - Real(4) * a * (c * c * c) + - Real(27) * (a * a) * (d * d); + */ + // discriminant > 0 => 3 distinct, real roots. + // discriminant = 0 => a multiple root (1 or 2 real roots) + // discriminant < 0 => 1 real root, 2 complex conjugate roots + + ////HACK: We know any roots we care about will be between 0 and 1, so... + Real maxi(100); + Real prevRes(d); + std::vector roots; + for(int i = 0; i <= 100; ++i) + { + Real x(i); + x /= maxi; + Real y = a*(x*x*x) + b*(x*x) + c*x + d; + if (y == Real(0) || (y < Real(0) && prevRes > Real(0)) || (y > Real(0) && prevRes < Real(0))) + { + roots.push_back(x); + } + } + return roots; + + } + + /** A _cubic_ bezier. **/ struct Bezier { @@ -64,11 +98,16 @@ namespace IPDF Rect SolveBounds() const; + Bezier ToAbsolute(const Rect & bounds) const + { + return Bezier(*this, bounds); + } + /** Convert absolute control points to control points relative to bounds * (This basically does the opposite of the Copy constructor) * ie: If this is absolute, the returned Bezier will be relative to the bounds rectangle */ - Bezier CopyInverse(const Rect & bounds) const + Bezier ToRelative(const Rect & bounds) const { // x' <- (x - x0)/w etc // special cases when w or h = 0