X-Git-Url: https://git.ucc.asn.au/?p=ipdf%2Fcode.git;a=blobdiff_plain;f=src%2Fpath.cpp;h=cae1e68b399eb9e05096afc9e6a28eefa4760345;hp=050453b5d7ff9b26575b9d73923acf9851434fd2;hb=180d764223a3568f734434a15d56f18e9ddc012b;hpb=3172dd5af487e0f8a6e5cd5439dea594b9cbd7c9 diff --git a/src/path.cpp b/src/path.cpp index 050453b..cae1e68 100644 --- a/src/path.cpp +++ b/src/path.cpp @@ -5,8 +5,8 @@ using namespace std; namespace IPDF { -Path::Path(const Objects & objects, unsigned start, unsigned end, const Colour & fill) - : m_start(start), m_end(end), m_fill(fill) +Path::Path(Objects & objects, unsigned start, unsigned end, const Colour & fill, const Colour & stroke) + : m_start(start), m_end(end), m_fill(fill), m_stroke(stroke) { Real xmin = 0; Real ymin = 0; Real xmax = 0; Real ymax = 0; @@ -14,13 +14,15 @@ Path::Path(const Objects & objects, unsigned start, unsigned end, const Colour & // Find the bounds coordinates // and identify the top left and bottom right objects - unsigned left; - unsigned right; - unsigned top; - unsigned bottom; + unsigned left = m_start; + unsigned right = m_start; + unsigned top = m_start; + unsigned bottom = m_start; for (unsigned i = m_start; i <= m_end; ++i) { + if (i >= objects.bounds.size()) + break; const Rect & objb = objects.bounds[i]; if (i == m_start || objb.x < xmin) @@ -43,26 +45,161 @@ Path::Path(const Objects & objects, unsigned start, unsigned end, const Colour & { ymax = (objb.y+objb.h); bottom = i; - } + } } // Get actual turning point coords of the 4 edge case beziers m_top = objects.beziers[objects.data_indices[top]].ToAbsolute(objects.bounds[top]).GetTop(); 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); - */ + m_right = objects.beziers[objects.data_indices[right]].ToAbsolute(objects.bounds[right]).GetRight(); + + m_bounds = SolveBounds(objects).Convert(); + #ifdef TRANSFORM_BEZIERS_TO_PATH + for (unsigned i = m_start; i <= m_end; ++i) + { + //Debug("Transform %s -> %s", objects.bounds[i].Str().c_str(), bounds.Str().c_str()); + objects.bounds[i] = TransformRectCoordinates(m_bounds.Convert(), objects.bounds[i]); + //Debug("-> %s", objects.bounds[i].Str().c_str()); + } + #endif +} + + +bool Path::PointInside(const Objects & objects, const Vec2 & pt, bool debug) const +{ + vector x_ints; + vector y_ints; + for (unsigned i = m_start; i <= m_end; ++i) + { + Bezier bez(objects.beziers[objects.data_indices[i]].ToAbsolute(objects.bounds[i])); + vector xi(bez.SolveX(pt.x)); + vector 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,Double(x_ints[i].x), Double(x_ints[i].y), Double(pt.x), Double(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,Double(y_ints[i].x), Double(y_ints[i].y), Double(pt.x), Double(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; +} + +vector & Path::FillPoints(const Objects & objects, const View & view) +{ + //if (m_fill_points.size() != 0) + return m_fill_points; + + + for (unsigned i = m_start; i <= m_end; ++i) + { + const Rect & objb = objects.bounds[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); + + + } + + // 4 extrema + 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); + + return m_fill_points; +} + +Rect Path::SolveBounds(const Objects & objects) +{ + return Rect(m_left.x, m_top.y, m_right.x-m_left.x, m_bottom.y-m_top.y); } -Rect Path::SolveBounds(const Objects & objects) const +Rect & Path::GetBounds(Objects & objects) { - return Rect(m_left.first, m_top.second, m_right.first-m_left.first, m_bottom.second-m_top.second); + objects.bounds[m_index] = m_bounds.Convert(); + return objects.bounds[m_index]; } }