From: David Gow Date: Wed, 20 Aug 2014 17:13:22 +0000 (+0800) Subject: Totally break Quadtree Béziers. X-Git-Url: https://git.ucc.asn.au/?p=ipdf%2Fcode.git;a=commitdiff_plain;h=101df292750d2fe8ed1de541db197dd792232458 Totally break Quadtree Béziers. --- diff --git a/src/bezier.h b/src/bezier.h index 8e7cedc..6dac0d5 100644 --- a/src/bezier.h +++ b/src/bezier.h @@ -183,6 +183,61 @@ namespace IPDF return new_bezier; } + std::vector ClipToRectangle(const Rect& r) + { + // Find points of intersection with the rectangle. + + // Convert bezier coefficients -> cubic coefficients + Real xa = x0-x1+x2-x3; + Real xb = x1 - Real(2)*x2 + Real(3)*x3; + Real xc = x2 - Real(3)*x3; + Real xd = x3 + r.x; + + // Find its roots. + std::vector x_intersection = SolveCubic(xa, xb, xc, xd); + + // And for the other side. + xd = x3 + r.x + r.w; + + std::vector x_intersection_pt2 = SolveCubic(xa, xb, xc, xd); + x_intersection.insert(x_intersection.end(), x_intersection_pt2.begin(), x_intersection_pt2.end()); + + // Similarly for y-coordinates. + // Convert bezier coefficients -> cubic coefficients + Real ya = y0-y1+y2-y3; + Real yb = y1 - Real(2)*y2 + Real(3)*y3; + Real yc = y2 - Real(3)*y3; + Real yd = y3 + r.y; + + // Find its roots. + std::vector y_intersection = SolveCubic(ya, yb, yc, yd); + + // And for the other side. + yd = y3 + r.y + r.h; + + std::vector y_intersection_pt2 = SolveCubic(ya, yb, yc, yd); + y_intersection.insert(y_intersection.end(), y_intersection_pt2.begin(), y_intersection_pt2.end()); + + // Merge and sort. + x_intersection.insert(x_intersection.end(), y_intersection.begin(), y_intersection.end()); + + Debug("Found %d intersections.\n", x_intersection.size()); + + std::vector all_beziers; + if (x_intersection.empty()) + { + all_beziers.push_back(*this); + return all_beziers; + } + Real t0 = *(x_intersection.begin()); + for (auto it = x_intersection.begin()+1; it != x_intersection.end(); ++it) + { + Real t1 = *it; + all_beziers.push_back(this->ReParametrise(t0, t1)); + t0 = t1; + } + return all_beziers; + } /** Evaluate the Bezier at parametric parameter u, puts resultant point in (x,y) **/ void Evaluate(Real & x, Real & y, const Real & u) const diff --git a/src/document.cpp b/src/document.cpp index c4ba210..0b43cfc 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -130,8 +130,20 @@ int Document::ClipObjectToQuadChild(int object_id, QuadTreeNodeChildren type) m_objects.data_indices.push_back(m_objects.data_indices[object_id]); return 1; } - case GROUP: - break; + case BEZIER: + { + Rect child_node_bounds = TransformFromQuadChild({0,0,1,1}, type); + std::vector new_curves = m_objects.beziers[m_objects.data_indices[object_id]].ClipToRectangle(child_node_bounds); + Rect obj_bounds = TransformToQuadChild(m_objects.bounds[object_id], type); + for (size_t i = 0; i < new_curves.size(); ++i) + { + unsigned index = AddBezierData(new_curves[i]); + m_objects.bounds.push_back(obj_bounds); + m_objects.types.push_back(BEZIER); + m_objects.data_indices.push_back(index); + } + return new_curves.size(); + } default: Debug("Adding %s -> %s", m_objects.bounds[object_id].Str().c_str(), TransformToQuadChild(m_objects.bounds[object_id], type).Str().c_str()); m_objects.bounds.push_back(TransformToQuadChild(m_objects.bounds[object_id], type));