Careful, you may have to shade your eyes
authorSam Moore <matches@ucc.asn.au>
Thu, 28 Aug 2014 23:05:41 +0000 (07:05 +0800)
committerSam Moore <matches@ucc.asn.au>
Thu, 28 Aug 2014 23:05:41 +0000 (07:05 +0800)
Except for all the things that don't quite work, shading works perfectly.

src/bezier.cpp
src/bezier.h
src/document.cpp
src/main.h
src/objectrenderer.cpp
src/objectrenderer.h
src/path.cpp
src/path.h
src/real.h
src/view.cpp

index 1c83660..3fa16e3 100644 (file)
@@ -9,6 +9,113 @@ using namespace std;
 namespace IPDF
 {
 
+vector<Real> SolveQuadratic(const Real & a, const Real & b, const Real & c, const Real & min, const Real & max)
+{
+       vector<Real> roots; roots.reserve(2);
+       if (a == 0 && b != 0)
+       {
+               roots.push_back(-c/b);
+               return roots;
+       }
+       Real disc(b*b - Real(4)*a*c);
+       if (disc < 0)
+       {
+               return roots;
+       }
+       else if (disc == 0)
+       {
+               Real x(-b/Real(2)*a);
+               if (x >= min && x <= max)
+                       roots.push_back(x);
+               return roots;
+       }
+       
+       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));
+       if (x0 > x1)
+       {
+               Real tmp(x0);
+               x0 = x1;
+               x1 = tmp;
+       }
+       if (x0 >= min && x0 <= max)
+               roots.push_back(x0);
+       if (x1 >= min && x1 <= max)
+               roots.push_back(x1);
+       return roots;
+}
+
+/**
+ * Finds the root (if it exists) in a monotonicly in(de)creasing segment of a Cubic
+ */
+
+static void CubicSolveSegment(vector<Real> & roots, const Real & a, const Real & b, const Real & c, const Real & d, Real & tl, Real & tu, const Real & delta)
+{
+       Real l = a*tl*tl*tl + b*tl*tl + c*tl + d;
+       Real u = a*tu*tu*tu + b*tu*tu + c*tu + d;
+       if ((l < 0 && u < 0) || (l > 0 && u > 0))
+               return;
+       
+       bool negative = (u < l); // lower point > 0, upper point < 0
+       while (tu - tl > delta)
+       {
+               Real t(tu+tl);
+               t /= 2;
+               Real m = a*t*t*t + b*t*t + c*t + d;
+               if (m > 0)
+               {
+                       if (negative)
+                               tl = t;
+                       else
+                               tu = t;
+               }
+               else if (negative)
+               {
+                       tu = t;
+               }
+               else
+               {
+                       tl = t;
+               }
+               //Debug("Delta is %f (%f - %f -> %f)", tu-tl, tu, tl, t);
+       }
+       roots.push_back(tl);
+}
+vector<Real> SolveCubic(const Real & a, const Real & b, const Real & c, const Real & d, const Real & min, const Real & max, const Real & delta)
+{
+       vector<Real> roots; roots.reserve(3);
+       Real tu(max);
+       Real tl(min);
+       vector<Real> turns(SolveQuadratic(a*3, b*2, c));
+       //Debug("%u turning points", turns.size());
+       for (unsigned i = 1; i < turns.size(); ++i)
+       {
+               tu = turns[i];
+               CubicSolveSegment(roots, a, b, c, d, tl, tu,delta);
+               tl = turns[i];
+       }
+       tu = max;
+       CubicSolveSegment(roots, a, b, c, d, tl, tu,delta);
+       return roots;
+       /*
+               Real maxi(100);
+               Real prevRes(d);
+               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)) && (prevRes > Real(0))) || ((y > Real(0)) && (prevRes < Real(0))))
+                       {
+                               //Debug("Found root of %fx^3 + %fx^2 + %fx + %f at %f (%f)", a, b, c, d, x, y);
+                               roots.push_back(x);
+                       }
+                       prevRes = y;
+               }
+               return roots;
+       */
+}
+
 /**
  * Factorial
  * Use dynamic programming / recursion
@@ -77,12 +184,14 @@ pair<Real, Real> BezierTurningPoints(const Real & p0, const Real & p1, const Rea
                //Debug("No real roots");
                return pair<Real, Real>(0,1);
        }
-       pair<Real, Real> tsols = SolveQuadratic(a, b, c);
-       if (tsols.first > 1) tsols.first = 1;
-       if (tsols.first < 0) tsols.first = 0;
-       if (tsols.second > 1) tsols.second = 1;
-       if (tsols.second < 0) tsols.second = 0;
-       return tsols;
+       vector<Real> tsols = SolveQuadratic(a, b, c);
+       if (tsols.size() == 1)
+               return pair<Real,Real>(tsols[0], tsols[0]);
+       else if (tsols.size() == 0)
+               return pair<Real, Real>(0,1);
+       
+       return pair<Real,Real>(tsols[0], tsols[1]);
+       
 }
 
 inline bool CompRealByPtr(const Real * a, const Real * b) 
@@ -239,6 +348,47 @@ pair<Real,Real> Bezier::GetRight() const
        return result;
 }
 
+vector<Real> Bezier::SolveXParam(const Real & x) const
+{
+       Real d(x0 - x);
+       Real c((x1 - x0)*Real(3));
+       Real b((x2 - x1)*Real(3) - c);
+       Real a(x3 -x0 - c - b);
+       vector<Real> results(SolveCubic(a, b, c, d));
+       for (unsigned i = 0; i < results.size(); ++i)
+       {
+               Vec2 p;
+               Evaluate(p.x, p.y, results[i]);
+       }
+       return results;
+}
+
+
+vector<Real> Bezier::SolveYParam(const Real & y) const
+{
+       Real d(y0 - y);
+       Real c((y1 - y0)*Real(3));
+       Real b((y2 - y1)*Real(3) - c);
+       Real a(y3 -y0 - c - b);
+       vector<Real> results(SolveCubic(a, b, c, d));
+       for (unsigned i = 0; i < results.size(); ++i)
+       {
+               Vec2 p;
+               Evaluate(p.x, p.y, results[i]);
+       }
+       return results;
+}
+
+vector<Vec2> Bezier::Evaluate(const vector<Real> & u) const
+{
+       vector<Vec2> result(u.size());
+       for (unsigned i = 0; i < u.size(); ++i)
+       {
+               Evaluate(result[i].x, result[i].y, u[i]);
+       }
+       return result;
+}
+
 /**
  * Get Bounds Rectangle of Bezier
  */
index 9dd38c0..7ff4f87 100644 (file)
@@ -13,65 +13,9 @@ namespace IPDF
        extern Real Bernstein(int k, int n, const Real & u);
        extern std::pair<Real,Real> BezierTurningPoints(const Real & p0, const Real & p1, const Real & p2, const Real & p3);
        
-       inline std::pair<Real,Real> 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));
-               return std::pair<Real,Real>(x0,x1);
-       }
-
-       inline std::vector<Real> 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
-
-               std::vector<Real> roots;
-               // delta = 18abcd - 4 b^3 d + b^2 c^2 - 4ac^3 - 27 a^2 d^2
-               
-#if 0
-               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);
-               
-               Debug("Trying to solve %fx^3 + %fx^2 + %fx + %f (Discriminant: %f)", a,b,c,d, discriminant);
-               // 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
-
-               Real delta0 = (b*b) - Real(3) * a * c;
-               Real delta1 = Real(2) * (b * b * b) - Real(9) * a * b * c + Real(27) * (a * a) * d;
+       extern std::vector<Real> SolveQuadratic(const Real & a, const Real & b, const Real & c, const Real & min = 0, const Real & max = 1);
 
-
-               Real C = pow((delta1 + Sqrt((delta1 * delta1) - 4 * (delta0 * delta0 * delta0)) ) / Real(2), 1/3);
-
-               if (false && discriminant < 0)
-               {
-                       Real real_root = (Real(-1) / (Real(3) * a)) * (b + C + delta0 / C);
-
-                       roots.push_back(real_root);
-
-                       return roots;
-
-               }
-#endif
-               ////HACK: We know any roots we care about will be between 0 and 1, so...
-               Real maxi(100);
-               Real prevRes(d);
-               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)) && (prevRes > Real(0))) || ((y > Real(0)) && (prevRes < Real(0))))
-                       {
-                               Debug("Found root of %fx^3 + %fx^2 + %fx + %f at %f (%f)", a, b, c, d, x, y);
-                               roots.push_back(x);
-                       }
-                       prevRes = y;
-               }
-               return roots;
-                       
-       }
+       extern std::vector<Real> SolveCubic(const Real & a, const Real & b, const Real & c, const Real & d, const Real & min = 0, const Real & max = 1, const Real & delta = 1e-4);
 
        /** A _cubic_ bezier. **/
        struct Bezier
@@ -327,6 +271,21 @@ namespace IPDF
                        x = x0*coeff[0] + x1*coeff[1] + x2*coeff[2] + x3*coeff[3];
                        y = y0*coeff[0] + y1*coeff[1] + y2*coeff[2] + y3*coeff[3];
                }
+               std::vector<Vec2> Evaluate(const std::vector<Real> & u) const;
+               
+               std::vector<Real> SolveXParam(const Real & x) const;
+               std::vector<Real> SolveYParam(const Real & x) const;
+               
+               // Get points with same X
+               inline std::vector<Vec2> SolveX(const Real & x) const
+               {
+                       return Evaluate(SolveXParam(x));
+               }
+               // Get points with same Y
+               inline std::vector<Vec2> SolveY(const Real & y) const
+               {
+                       return Evaluate(SolveYParam(y));
+               }
                
                bool operator==(const Bezier & equ) const
                {
index 1383906..5ba166c 100644 (file)
@@ -313,9 +313,9 @@ unsigned Document::AddBezier(const Bezier & bezier)
        Bezier data = bezier.ToRelative(bounds); // Relative
        if (data.ToAbsolute(bounds) != bezier)
        {
-               Error("%s != %s", data.ToAbsolute(Rect(0,0,1,1)).Str().c_str(),
+               Warn("%s != %s", data.ToAbsolute(Rect(0,0,1,1)).Str().c_str(),
                        bezier.Str().c_str());
-               Fatal("ToAbsolute on ToRelative does not give original Bezier");
+               Warn("ToAbsolute on ToRelative does not give original Bezier");
        }
        unsigned index = AddBezierData(data);
        return Add(BEZIER, bounds, index);
index 5ca71ef..88aebfe 100644 (file)
@@ -94,7 +94,7 @@ inline void MainLoop(Document & doc, Screen & scr, View & view)
        clock_gettime(CLOCK_MONOTONIC_RAW, &real_clock_start);
        real_clock_now = real_clock_start;
        double frames = 0;
-       double data_rate = 1; // period between data output to stdout (if <= 0 there will be no output)
+       double data_rate = 0; // period between data output to stdout (if <= 0 there will be no output)
        uint64_t data_points = 0;
        setbuf(stdout, NULL);
        while (scr.PumpEvents())
index 8234547..f39bae8 100644 (file)
@@ -6,6 +6,7 @@
 #include "objectrenderer.h"
 #include "view.h"
 #include <vector>
+#include <queue>
 
 using namespace std;
 
@@ -213,13 +214,13 @@ Rect ObjectRenderer::CPURenderBounds(const Rect & bounds, const View & view, con
        return result;
 }
 
-pair<int64_t, int64_t> ObjectRenderer::CPUPointLocation(const pair<Real, Real> & point, const View & view, const CPURenderTarget & target)
+ObjectRenderer::PixelPoint ObjectRenderer::CPUPointLocation(const Vec2 & point, const View & view, const CPURenderTarget & target)
 {
        // hack...
-       Rect result = view.TransformToViewCoords(Rect(point.first, point.second,1,1));
+       Rect result = view.TransformToViewCoords(Rect(point.x, point.y,1,1));
        int64_t x = result.x*target.w;
        int64_t y = result.y*target.h;
-       return pair<int64_t, int64_t>(x,y);
+       return PixelPoint(x,y);
 }
        
 
@@ -263,7 +264,7 @@ void BezierRenderer::RenderUsingCPU(const Objects & objects, const View & view,
                for (int64_t j = 1; j <= blen; ++j)
                {
                        control.Evaluate(x[j % 2],y[j % 2], invblen*j);
-                       ObjectRenderer::RenderLineOnCPU((int64_t)Double(x[0]),(int64_t)Double(y[0]), (int64_t)Double(x[1]),(int64_t)Double(y[1]), target);
+                       ObjectRenderer::RenderLineOnCPU((int64_t)Double(x[0]),(int64_t)Double(y[0]), (int64_t)Double(x[1]),(int64_t)Double(y[1]), target, Colour(0,0,0,!view.PerformingShading()));
                }
                
                /*
@@ -362,35 +363,27 @@ void PathRenderer::RenderUsingCPU(const Objects & objects, const View & view, co
                
                Rect bounds(CPURenderBounds(objects.bounds[m_indexes[i]], view, target));
                PixelBounds pix_bounds(bounds);
-               pix_bounds.x-=1;
-               pix_bounds.w+=2;
-               pix_bounds.y-=1;
-               pix_bounds.h+=2;
                const Path & path = objects.paths[objects.data_indices[m_indexes[i]]];
                if (path.m_fill.a == 0 || !view.PerformingShading())
                        continue;
-
-
-               pair<int64_t,int64_t> top(CPUPointLocation(path.m_top, view, target));
-               pair<int64_t,int64_t> bottom(CPUPointLocation(path.m_bottom, view, target));
-               pair<int64_t,int64_t> left(CPUPointLocation(path.m_left, view, target));
-               pair<int64_t,int64_t> right(CPUPointLocation(path.m_right, view, target));
-               FloodFillOnCPU(top.first, top.second+1, pix_bounds, target, path.m_fill);
-               FloodFillOnCPU(bottom.first, bottom.second-1, pix_bounds, target, path.m_fill);
-               FloodFillOnCPU(left.first+1, left.second, pix_bounds, target, path.m_fill);
-               FloodFillOnCPU(right.first-1, right.second, pix_bounds, target, path.m_fill);
                
-               if (view.ShowingObjectBounds())
+               for (unsigned f = 0; f < path.m_fill_points.size(); ++f)
                {
-                       Colour c(0,0,1,1);
-                       RenderLineOnCPU(top.first, top.second, bottom.first, bottom.second, target, c);
-                       RenderLineOnCPU(left.first, left.second, right.first, right.second, target, c);
-                       ObjectRenderer::RenderLineOnCPU(pix_bounds.x, pix_bounds.y, pix_bounds.x+pix_bounds.w, pix_bounds.y, target, c);
-                       ObjectRenderer::RenderLineOnCPU(pix_bounds.x, pix_bounds.y+pix_bounds.h, pix_bounds.x+pix_bounds.w, pix_bounds.y+pix_bounds.h, target, c);
-                       ObjectRenderer::RenderLineOnCPU(pix_bounds.x, pix_bounds.y, pix_bounds.x, pix_bounds.y+pix_bounds.h, target, c);
-                       ObjectRenderer::RenderLineOnCPU(pix_bounds.x+pix_bounds.w, pix_bounds.y, pix_bounds.x+pix_bounds.w, pix_bounds.y+pix_bounds.h, target, c);
+                       PixelPoint fill_point(CPUPointLocation(path.m_fill_points[f], view, target));
+                       FloodFillOnCPU(fill_point.first, fill_point.second, pix_bounds, target, path.m_fill);
                }
                
+               /*if (true)//(view.ShowingObjectBounds())
+               {
+                       
+                       PixelPoint start(CPUPointLocation((path.m_top+path.m_left+path.m_right+path.m_bottom)/4, view, target));
+                       for (unsigned f = 0; f < path.m_fill_points.size(); ++f)
+                       {
+                               PixelPoint end(CPUPointLocation(path.m_fill_points[f], view, target));
+                               RenderLineOnCPU(start.first, start.second, end.first, end.second, target, Colour(0,0,1,1));
+                       }
+               }
+               */
        
        }       
 }
@@ -494,20 +487,28 @@ void ObjectRenderer::RenderLineOnCPU(int64_t x0, int64_t y0, int64_t x1, int64_t
 
 void ObjectRenderer::FloodFillOnCPU(int64_t x, int64_t y, const PixelBounds & bounds, const CPURenderTarget & target, const Colour & fill)
 {
-       if (x < 0 || x < bounds.x || x > bounds.x+bounds.w || x >= target.w)
-               return;
-       if (y < 0 || y < bounds.y || y > bounds.y+bounds.h || y >= target.h)
-               return;
-               
-       if (GetColour(target, x, y) != Colour(1,1,1,1))
+       if (fill == Colour(1,1,1,1))
                return;
+       queue<PixelPoint > traverse;
+       traverse.push(PixelPoint(x,y));
+       // now with 100% less stack overflows!
+       while (traverse.size() > 0)
+       {
+               PixelPoint cur(traverse.front());
+               traverse.pop();
+               if (cur.first < 0 || cur.first < bounds.x || cur.first >= bounds.x+bounds.w || cur.first >= target.w ||
+                       cur.second < 0 || cur.second < bounds.y || cur.second >= bounds.y+bounds.h || cur.second >= target.h)
+                       continue;
+               if (GetColour(target, cur.first, cur.second) != Colour(1,1,1,1))
+                       continue;
+               SetColour(target, cur.first, cur.second, fill);
                
-       SetColour(target, x, y, fill);
-       FloodFillOnCPU(x-1, y, bounds, target, fill);
-       FloodFillOnCPU(x+1, y, bounds, target, fill);
-       FloodFillOnCPU(x,y-1,bounds,target,fill);
-       FloodFillOnCPU(x,y+1,bounds,target,fill);
-       
+
+               traverse.push(PixelPoint(cur.first+1, cur.second));
+               traverse.push(PixelPoint(cur.first-1, cur.second));
+               traverse.push(PixelPoint(cur.first, cur.second-1));
+               traverse.push(PixelPoint(cur.first, cur.second+1)); 
+       }
 }
 
 }
index 66daafb..e43e3b9 100644 (file)
@@ -75,9 +75,11 @@ namespace IPDF
                                int64_t x; int64_t y; int64_t w; int64_t h;
                                PixelBounds(const Rect & bounds) : x(Double(bounds.x)), y(Double(bounds.y)), w(Double(bounds.w)), h(Double(bounds.h)) {}
                        };
+                       
+                       typedef std::pair<int64_t, int64_t> PixelPoint;
 
                        static Rect CPURenderBounds(const Rect & bounds, const View & view, const CPURenderTarget & target);
-                       static std::pair<int64_t, int64_t> CPUPointLocation(const std::pair<Real, Real> & point, const View & view, const CPURenderTarget & target);
+                       static PixelPoint CPUPointLocation(const Vec2 & point, const View & view, const CPURenderTarget & target);
 
                        static void SaveBMP(const CPURenderTarget & target, const char * filename);
 
index 050453b..e0eca4a 100644 (file)
@@ -44,6 +44,49 @@ Path::Path(const Objects & objects, unsigned start, unsigned end, const Colour &
                        ymax = (objb.y+objb.h);
                        bottom = i;
                }
+               
+               // find fill points
+               Vec2 pt;
+               // left
+               pt = Vec2(objb.x, objb.y+objb.h/Real(2));
+               if (PointInside(objects, pt))
+                       m_fill_points.push_back(pt);
+               // right
+               pt = Vec2(objb.x+objb.w, objb.y+objb.h/Real(2));
+               if (PointInside(objects, pt))
+                       m_fill_points.push_back(pt);
+               // bottom
+               pt = Vec2(objb.x+objb.w/Real(2), objb.y+objb.h);
+               if (PointInside(objects, pt))
+                       m_fill_points.push_back(pt);
+               // top
+               pt = Vec2(objb.x+objb.w/Real(2), objb.y);
+               if (PointInside(objects, pt))
+                       m_fill_points.push_back(pt);
+                       
+               // topleft
+               pt = Vec2(objb.x, objb.y);
+               if (PointInside(objects, pt))
+                       m_fill_points.push_back(pt);
+               // topright
+               pt = Vec2(objb.x+objb.w, objb.y);
+               if (PointInside(objects, pt))
+                       m_fill_points.push_back(pt);
+               // bottom left
+               pt = Vec2(objb.x, objb.y+objb.h);
+               if (PointInside(objects, pt))
+                       m_fill_points.push_back(pt);
+               // bottom right
+               pt = Vec2(objb.x+objb.w, objb.y);
+               if (PointInside(objects, pt))
+                       m_fill_points.push_back(pt);
+                       
+               // mid
+               pt = Vec2(objb.x+objb.w/Real(2), objb.y+objb.h/Real(2));
+               if (PointInside(objects, pt))
+                       m_fill_points.push_back(pt);
+               
+               
        }
        
        // Get actual turning point coords of the 4 edge case beziers
@@ -51,18 +94,81 @@ Path::Path(const Objects & objects, unsigned start, unsigned end, const Colour &
        m_bottom = objects.beziers[objects.data_indices[bottom]].ToAbsolute(objects.bounds[bottom]).GetBottom();
        m_left = objects.beziers[objects.data_indices[left]].ToAbsolute(objects.bounds[left]).GetLeft();
        m_right = objects.beziers[objects.data_indices[right]].ToAbsolute(objects.bounds[right]).GetRight();
-       /*Debug("Top: %f, %f", m_top.first, m_top.second);
-       Debug("Bottom: %f, %f", m_bottom.first, m_bottom.second);
-       Debug("Left: %f, %f", m_left.first, m_left.second);
-       Debug("Right: %f, %f", m_right.first, m_right.second);
-       Debug("Left - Right: %f, %f", m_right.first - m_left.first, m_right.second - m_left.second);
-       Debug("Top - Bottom: %f, %f", m_top.first - m_bottom.first, m_top.second - m_bottom.second);
-       */
+       
+       Vec2 pt = (m_top + m_bottom)/2;
+       if (PointInside(objects, pt))
+               m_fill_points.push_back(pt);
+       pt = (m_left + m_right)/2;
+       if (PointInside(objects, pt))
+               m_fill_points.push_back(pt);
+       pt = (m_left + m_right + m_top + m_bottom)/4;
+       if (PointInside(objects, pt))
+               m_fill_points.push_back(pt);
+               
+}
+
+
+bool Path::PointInside(const Objects & objects, const Vec2 & pt, bool debug) const
+{
+       vector<Vec2> x_ints;
+       vector<Vec2> y_ints;
+       for (unsigned i = m_start; i <= m_end; ++i)
+       {
+               Bezier bez(objects.beziers[objects.data_indices[i]].ToAbsolute(objects.bounds[i]));
+               vector<Vec2> xi(bez.SolveX(pt.x));
+               vector<Vec2> yi(bez.SolveY(pt.y));
+               x_ints.insert(x_ints.end(), xi.begin(), xi.end());
+               y_ints.insert(y_ints.end(), yi.begin(), yi.end());
+       }
+       //Debug("Solved for intersections");
+       unsigned bigger = 0;
+       unsigned smaller = 0;
+       for (unsigned i = 0; i < x_ints.size(); ++i)
+       {
+               if (debug)
+                               Debug("X Intersection %u at %f,%f vs %f,%f", i,x_ints[i].x, x_ints[i].y, pt.x, pt.y);
+               if (x_ints[i].y >= pt.y)
+               {
+                       
+                       ++bigger;
+               }
+       }
+       smaller = x_ints.size() - bigger;
+       if (debug)
+       {
+               Debug("%u horizontal, %u bigger, %u smaller", x_ints.size(), bigger, smaller);
+       }
+       if (smaller % 2 == 0 || bigger % 2 == 0)
+               return false;
+               
+       bigger = 0;
+       smaller = 0;
+
+       for (unsigned i = 0; i < y_ints.size(); ++i)
+       {
+               if (debug)
+                               Debug("Y Intersection %u at %f,%f vs %f,%f", i,x_ints[i].x, x_ints[i].y, pt.x, pt.y);
+               if (y_ints[i].x >= pt.x)
+               {
+                       
+                       ++bigger;
+               }
+       }
+       smaller = y_ints.size() - bigger;
+       if (debug)
+       {
+               Debug("%u vertical, %u bigger, %u smaller", y_ints.size(), bigger, smaller);
+       }
+       if (smaller % 2 == 0 || bigger % 2 == 0)
+               return false;
+               
+               
+       return true;
 }
 
 Rect Path::SolveBounds(const Objects & objects) const
 {
-               return Rect(m_left.first, m_top.second, m_right.first-m_left.first, m_bottom.second-m_top.second);
+               return Rect(m_left.x, m_top.y, m_right.x-m_left.x, m_bottom.y-m_top.y);
 }
 
 }
index ac6956c..b08c146 100644 (file)
@@ -29,16 +29,19 @@ namespace IPDF
                
                Rect SolveBounds(const Objects & objects) const;
                
-               
+               // Is point inside shape?
+               bool PointInside(const Objects & objects, const Vec2 & pt, bool debug=false) const;
                
                unsigned m_start; // First bounding Bezier index
                unsigned m_end; // Last (inclusive) '' ''
                unsigned m_index; // index into Objects array
                
-               std::pair<Real,Real> m_top;
-               std::pair<Real,Real> m_bottom;
-               std::pair<Real,Real> m_left;
-               std::pair<Real,Real> m_right;
+               Vec2 m_top;
+               Vec2 m_bottom;
+               Vec2 m_left;
+               Vec2 m_right;
+               
+               std::vector<Vec2> m_fill_points;
                
                Colour m_fill;  // colour to fill with  
        };
index 2be3fdd..b766558 100644 (file)
@@ -88,6 +88,7 @@ namespace IPDF
                Real y;
                Vec2() : x(0), y(0) {}
                Vec2(Real _x, Real _y) : x(_x), y(_y) {}
+               Vec2(const std::pair<Real, Real> & p) : x(p.first), y(p.second) {}
        
                bool operator==(const Vec2& other) const { return (x == other.x) && (y == other.y); }
                bool operator!=(const Vec2& other) const { return !(*this == other); }
index 8f4a8a4..2caaadc 100644 (file)
@@ -253,7 +253,7 @@ void View::Render(int width, int height)
        {
                m_screen.RenderPixels(0,0,width, height, m_cpu_rendering_pixels); //TODO: Make this work :(
                // Debug for great victory (do something similar for GPU and compare?)
-               ObjectRenderer::SaveBMP({m_cpu_rendering_pixels, width, height}, "cpu_rendering_last_frame.bmp");
+               //ObjectRenderer::SaveBMP({m_cpu_rendering_pixels, width, height}, "cpu_rendering_last_frame.bmp");
        }
        m_cached_display.UnBind(); // resets render target to the screen
        m_cached_display.Blit(); // blit FrameBuffer to screen

UCC git Repository :: git.ucc.asn.au