/** Make a path from a d2 sbasis. \param p the d2 Symmetric basis polynomial \returns a Path If only_cubicbeziers is true, the resulting path may only contain CubicBezier curves. TODO: some of this logic should be lifted into svg-path */ std::vector<Geom::Path> path_from_piecewise(Geom::Piecewise<Geom::D2<Geom::SBasis> > const &B, double tol, bool only_cubicbeziers) { Geom::PathBuilder pb; if(B.size() == 0) return pb.peek(); Geom::Point start = B[0].at0(); pb.moveTo(start); for(unsigned i = 0; ; i++) { if ( (i+1 == B.size()) || !are_near(B[i+1].at0(), B[i].at1(), tol) ) { //start of a new path if (are_near(start, B[i].at1()) && sbasis_size(B[i]) <= 1) { pb.closePath(); //last line seg already there (because of .closePath()) goto no_add; } build_from_sbasis(pb, B[i], tol, only_cubicbeziers); if (are_near(start, B[i].at1())) { //it's closed, the last closing segment was not a straight line so it needed to be added, but still make it closed here with degenerate straight line. pb.closePath(); } no_add: if (i+1 >= B.size()) { break; } start = B[i+1].at0(); pb.moveTo(start); } else { build_from_sbasis(pb, B[i], tol, only_cubicbeziers); } } pb.flush(); return pb.peek(); }
/** Make a path from a d2 sbasis. \param p the d2 Symmetric basis polynomial \returns a Path If only_cubicbeziers is true, the resulting path may only contain CubicBezier curves. */ Path path_from_sbasis(D2<SBasis> const &B, double tol, bool only_cubicbeziers) { PathBuilder pb; pb.moveTo(B.at0()); build_from_sbasis(pb, B, tol, only_cubicbeziers); pb.flush(); return pb.peek().front(); }
/** Make a path from a d2 sbasis. \param p the d2 Symmetric basis polynomial \returns a Path If only_cubicbeziers is true, the resulting path may only contain CubicBezier curves. */ void build_from_sbasis(Geom::PathBuilder &pb, D2<SBasis> const &B, double tol, bool only_cubicbeziers) { if (!B.isFinite()) { THROW_EXCEPTION("assertion failed: B.isFinite()"); } if(tail_error(B, 2) < tol || sbasis_size(B) == 2) { // nearly cubic enough if( !only_cubicbeziers && (sbasis_size(B) <= 1) ) { pb.lineTo(B.at1()); } else { std::vector<Geom::Point> bez; sbasis_to_bezier(bez, B, 4); pb.curveTo(bez[1], bez[2], bez[3]); } } else { build_from_sbasis(pb, compose(B, Linear(0, 0.5)), tol, only_cubicbeziers); build_from_sbasis(pb, compose(B, Linear(0.5, 1)), tol, only_cubicbeziers); } }