From 5eb7d43e7f43c68191ef9ec616b9bd48c9b6c251 Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Date: Fri, 1 Dec 2017 23:13:57 +0100 Subject: Working on BSpline interpolator --- src/live_effects/lpe-interpolate_points.cpp | 3 +- src/live_effects/lpe-powerstroke-interpolators.h | 78 +++++++++++++++++++++++- src/live_effects/lpe-powerstroke.cpp | 3 +- 3 files changed, 80 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/live_effects/lpe-interpolate_points.cpp b/src/live_effects/lpe-interpolate_points.cpp index 7d4c88dc1..c745921c2 100644 --- a/src/live_effects/lpe-interpolate_points.cpp +++ b/src/live_effects/lpe-interpolate_points.cpp @@ -25,7 +25,8 @@ static const Util::EnumData InterpolatorTypeData[] = { {Geom::Interpolate::INTERP_CUBICBEZIER , N_("CubicBezierFit"), "CubicBezierFit"}, {Geom::Interpolate::INTERP_CUBICBEZIER_JOHAN , N_("CubicBezierJohan"), "CubicBezierJohan"}, {Geom::Interpolate::INTERP_SPIRO , N_("SpiroInterpolator"), "SpiroInterpolator"}, - {Geom::Interpolate::INTERP_CENTRIPETAL_CATMULLROM, N_("Centripetal Catmull-Rom"), "CentripetalCatmullRom"} + {Geom::Interpolate::INTERP_CENTRIPETAL_CATMULLROM, N_("Centripetal Catmull-Rom"), "CentripetalCatmullRom"}, + {Geom::Interpolate::INTERP_BSPLINE , N_("BSpline"), "BSpline"} }; static const Util::EnumDataConverter InterpolatorTypeConverter(InterpolatorTypeData, sizeof(InterpolatorTypeData)/sizeof(*InterpolatorTypeData)); diff --git a/src/live_effects/lpe-powerstroke-interpolators.h b/src/live_effects/lpe-powerstroke-interpolators.h index e3ab37e27..0c1b60754 100644 --- a/src/live_effects/lpe-powerstroke-interpolators.h +++ b/src/live_effects/lpe-powerstroke-interpolators.h @@ -15,7 +15,7 @@ #include <2geom/path.h> #include <2geom/bezier-utils.h> #include <2geom/sbasis-to-bezier.h> - +#include #include "live_effects/spiro.h" @@ -29,7 +29,8 @@ enum InterpolatorType { INTERP_CUBICBEZIER_JOHAN, INTERP_SPIRO, INTERP_CUBICBEZIER_SMOOTH, - INTERP_CENTRIPETAL_CATMULLROM + INTERP_CENTRIPETAL_CATMULLROM, + INTERP_BSPLINE }; class Interpolator { @@ -65,6 +66,77 @@ private: Linear& operator=(const Linear&); }; +class BSpline : public Interpolator { +public: + BSpline() {}; + virtual ~BSpline() {}; + + virtual Path interpolateToPath(std::vector const &points) const { + Path path; + path.start( points.at(0) ); + + Geom::Point point_a = points.at(0); + Geom::Point point_b = points.at(1); + Geom::Point point_c = points.at(2); + Geom::Point point_d = points.at(2); + if (points.size() > 3) { + point_d = points.at(3); + } + Geom::Point handle_1 = point_a; + Geom::Point handle_2 = point_b; + Geom::Point node_1 = point_a; + Geom::Point node_2 = point_b; //if the line is straight with next + Geom::Line line_ab(point_a, point_b); + Geom::Line line_bc(point_b, point_c); + Geom::Line line_cd(point_c, point_d); + Geom::Point handle_next(line_bc.pointAt(0.33334)); //if the line is straight with next + Geom::Point center_ab = line_ab.pointAt(0.5); + Geom::Point center_bc = line_bc.pointAt(0.5); + Geom::Point center_cd = line_cd.pointAt(0.5); + Geom::Line cross_line_hlp(line_ab.pointAt(0.66667), center_cd); + Geom::Point cross_center_hlp = cross_line_hlp.pointAt(0.5); + double angle_ab = line_ab.angle(); + double angle_bc = line_bc.angle(); + double angle_cd = line_cd.angle(); + double cross_angle_hlp = cross_line_hlp.angle(); + Geom::Line perpend_ab(center_ab, center_ab + Geom::Point::polar(angle_ab + Geom::rad_from_deg(90),1)); + Geom::Line perpend_bc(center_bc, center_bc + Geom::Point::polar(angle_bc + Geom::rad_from_deg(90),1)); + Geom::Line cross_1 (cross_center_hlp, cross_center_hlp + Geom::Point::polar(cross_angle_hlp + Geom::rad_from_deg(90),1)); + std::vector cross_hlp = perpend_ab.intersect(perpend_bc); + if(cross_hlp.size() > 0) { + cross_line_hlp.setPoints(cross_hlp[0], line_ab.pointAt(0.66667)); + cross_angle_hlp = cross_line_hlp.angle(); + Geom::Line cross_2(line_ab.pointAt(0.66667), line_ab.pointAt(0.66667) + Geom::Point::polar(cross_angle_hlp + Geom::rad_from_deg(90),1)); + std::vector cross = cross_1.intersect(cross_2); + if(cross.size() > 0) { + Geom::Line handle_line(cross[0],point_b); + handle_2 = handle_line.pointAt(2.0); + Geom::Line rootline(points.at(0),handle_2); + handle_1 = rootline.pointAt(0.5); + node_2 = rootline.pointAt(1.5); + handle_next = cross[0]; + } + } + path.appendNew(handle_1, handle_2, points.at(1)); + for (unsigned int i = 2 ; i < points.size(); ++i) { + Geom::Line rootline(node_2, handle_next); + handle_2 = rootline.pointAt(2.0); + node_2 = rootline.pointAt(3.0); + path.appendNew(handle_next, handle_2, points.at(i)); + Geom::Line handleline(handle_2, points.at(i)); + handle_next = handleline.pointAt(2.0); + } + Geom::Point last = points.at(points.size()-1); + Geom::LineSegment last_segment(handle_next,last); + path.appendNew(last_segment.initialPoint(), last_segment.pointAt(0.5), last); + return path; + }; + +private: + BSpline(const BSpline&); + BSpline& operator=(const BSpline&); +}; + // this class is terrible class CubicBezierFit : public Interpolator { public: @@ -302,6 +374,8 @@ Interpolator::create(InterpolatorType type) { return new Geom::Interpolate::CubicBezierSmooth(); case INTERP_CENTRIPETAL_CATMULLROM: return new Geom::Interpolate::CentripetalCatmullRomInterpolator(); + case INTERP_BSPLINE: + return new Geom::Interpolate::BSpline(); default: return new Geom::Interpolate::Linear(); } diff --git a/src/live_effects/lpe-powerstroke.cpp b/src/live_effects/lpe-powerstroke.cpp index 170995b90..47543107b 100644 --- a/src/live_effects/lpe-powerstroke.cpp +++ b/src/live_effects/lpe-powerstroke.cpp @@ -123,7 +123,8 @@ static const Util::EnumData InterpolatorTypeData[] = { {Geom::Interpolate::INTERP_CUBICBEZIER , N_("CubicBezierFit"), "CubicBezierFit"}, {Geom::Interpolate::INTERP_CUBICBEZIER_JOHAN , N_("CubicBezierJohan"), "CubicBezierJohan"}, {Geom::Interpolate::INTERP_SPIRO , N_("SpiroInterpolator"), "SpiroInterpolator"}, - {Geom::Interpolate::INTERP_CENTRIPETAL_CATMULLROM, N_("Centripetal Catmull-Rom"), "CentripetalCatmullRom"} + {Geom::Interpolate::INTERP_CENTRIPETAL_CATMULLROM, N_("Centripetal Catmull-Rom"), "CentripetalCatmullRom"}, + {Geom::Interpolate::INTERP_BSPLINE , N_("BSpline"), "BSpline"} }; static const Util::EnumDataConverter InterpolatorTypeConverter(InterpolatorTypeData, sizeof(InterpolatorTypeData)/sizeof(*InterpolatorTypeData)); -- cgit v1.2.3