From db164d8341a6dca5cab6fdc4576234bc656ac6f7 Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Date: Sun, 12 Nov 2017 18:10:11 +0100 Subject: Base refactor --- src/live_effects/lpe-powerstroke.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'src/live_effects') diff --git a/src/live_effects/lpe-powerstroke.cpp b/src/live_effects/lpe-powerstroke.cpp index 51c8451a5..7c060a965 100644 --- a/src/live_effects/lpe-powerstroke.cpp +++ b/src/live_effects/lpe-powerstroke.cpp @@ -563,13 +563,19 @@ LPEPowerStroke::doEffect_path (Geom::PathVector const & path_in) Geom::PathVector path_out; if (path_in.empty()) { - return path_out; + return path_in; } Geom::PathVector pathv = pathv_to_linear_and_cubic_beziers(path_in); Geom::Piecewise > pwd2_in = pathv[0].toPwSb(); + if (!pwd2_in.size()) { + return path_in; + } Piecewise > der = derivative(pwd2_in); + if (!der.size()) { + return path_in; + } Piecewise > n = unitVector(der,0.0001); - if (!n.size() || !pwd2_in.size() || !n.size()) { + if (!n.size()) { return path_in; } n = rot90(n); @@ -639,10 +645,8 @@ LPEPowerStroke::doEffect_path (Geom::PathVector const & path_in) } LineJoinType jointype = static_cast(linejoin_type.get_value()); - - Piecewise > pwd2_out = compose(pwd2_in,x) + y*compose(n,x); + Piecewise > pwd2_out = compose(pwd2_in,x) + y*compose(n,x); Piecewise > mirrorpath = reverse( compose(pwd2_in,x) - y*compose(n,x)); - Geom::Path fixed_path = path_from_piecewise_fix_cusps( pwd2_out, y, jointype, miter_limit, LPE_CONVERSION_TOLERANCE); Geom::Path fixed_mirrorpath = path_from_piecewise_fix_cusps( mirrorpath, reverse(y), jointype, miter_limit, LPE_CONVERSION_TOLERANCE); if (pathv[0].closed()) { -- cgit v1.2.3 From 4c790c63b7918e2745420c082bfa13e69cec74bd Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Date: Sun, 19 Nov 2017 02:47:56 +0100 Subject: Working on fix smooth draw --- src/live_effects/parameter/powerstrokepointarray.cpp | 15 +++++++++++++++ src/live_effects/parameter/powerstrokepointarray.h | 1 + 2 files changed, 16 insertions(+) (limited to 'src/live_effects') diff --git a/src/live_effects/parameter/powerstrokepointarray.cpp b/src/live_effects/parameter/powerstrokepointarray.cpp index bc06e42ca..7e2da4cfd 100644 --- a/src/live_effects/parameter/powerstrokepointarray.cpp +++ b/src/live_effects/parameter/powerstrokepointarray.cpp @@ -89,6 +89,21 @@ PowerStrokePointArrayParam::recalculate_controlpoints_for_new_pwd2(Geom::Piecewi } } +/** call this method to recalculate the controlpoints when path is reversed.*/ +void +PowerStrokePointArrayParam::reverse_controlpoints() +{ + if (!last_pwd2.empty()) { + Geom::Piecewise > const & pwd2_in_reverse = reverse(last_pwd2); + for (unsigned int i = 0; i < _vector.size(); ++i) { + Geom::Point control_pos = last_pwd2.valueAt(_vector[i][Geom::X]); + double new_pos = Geom::nearest_time(control_pos, pwd2_in_reverse); + _vector[i][Geom::X] = new_pos; + } + write_to_SVG(); + } +} + float PowerStrokePointArrayParam::median_width() { size_t size = _vector.size(); diff --git a/src/live_effects/parameter/powerstrokepointarray.h b/src/live_effects/parameter/powerstrokepointarray.h index 621d3b969..b8e63e5f7 100644 --- a/src/live_effects/parameter/powerstrokepointarray.h +++ b/src/live_effects/parameter/powerstrokepointarray.h @@ -47,6 +47,7 @@ public: Geom::Piecewise > const & get_pwd2_normal() const { return last_pwd2_normal; } void recalculate_controlpoints_for_new_pwd2(Geom::Piecewise > const & pwd2_in); + void reverse_controlpoints(); void set_scale_width(double scale_width){_scale_width = scale_width;}; double _scale_width; friend class PowerStrokePointArrayParamKnotHolderEntity; -- cgit v1.2.3 From d91112f7116f50489bd93047f6e7bc0985512c68 Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Date: Sun, 19 Nov 2017 23:54:21 +0100 Subject: Working on coontinuing paths --- src/live_effects/lpe-powerstroke.cpp | 2 +- src/live_effects/parameter/powerstrokepointarray.cpp | 16 +++++++++++++--- src/live_effects/parameter/powerstrokepointarray.h | 2 +- 3 files changed, 15 insertions(+), 5 deletions(-) (limited to 'src/live_effects') diff --git a/src/live_effects/lpe-powerstroke.cpp b/src/live_effects/lpe-powerstroke.cpp index 7c060a965..e9943af4c 100644 --- a/src/live_effects/lpe-powerstroke.cpp +++ b/src/live_effects/lpe-powerstroke.cpp @@ -645,7 +645,7 @@ LPEPowerStroke::doEffect_path (Geom::PathVector const & path_in) } LineJoinType jointype = static_cast(linejoin_type.get_value()); - Piecewise > pwd2_out = compose(pwd2_in,x) + y*compose(n,x); + Piecewise > pwd2_out = compose(pwd2_in,x) + y*compose(n,x); Piecewise > mirrorpath = reverse( compose(pwd2_in,x) - y*compose(n,x)); Geom::Path fixed_path = path_from_piecewise_fix_cusps( pwd2_out, y, jointype, miter_limit, LPE_CONVERSION_TOLERANCE); Geom::Path fixed_mirrorpath = path_from_piecewise_fix_cusps( mirrorpath, reverse(y), jointype, miter_limit, LPE_CONVERSION_TOLERANCE); diff --git a/src/live_effects/parameter/powerstrokepointarray.cpp b/src/live_effects/parameter/powerstrokepointarray.cpp index 7e2da4cfd..289498498 100644 --- a/src/live_effects/parameter/powerstrokepointarray.cpp +++ b/src/live_effects/parameter/powerstrokepointarray.cpp @@ -90,18 +90,28 @@ PowerStrokePointArrayParam::recalculate_controlpoints_for_new_pwd2(Geom::Piecewi } /** call this method to recalculate the controlpoints when path is reversed.*/ -void -PowerStrokePointArrayParam::reverse_controlpoints() +std::vector +PowerStrokePointArrayParam::reverse_controlpoints(bool write) { + std::vector controlpoints; if (!last_pwd2.empty()) { Geom::Piecewise > const & pwd2_in_reverse = reverse(last_pwd2); for (unsigned int i = 0; i < _vector.size(); ++i) { Geom::Point control_pos = last_pwd2.valueAt(_vector[i][Geom::X]); double new_pos = Geom::nearest_time(control_pos, pwd2_in_reverse); + controlpoints.push_back(Geom::Point(new_pos,_vector[i][Geom::Y])); _vector[i][Geom::X] = new_pos; } - write_to_SVG(); + if (write) { + write_to_SVG(); + _vector.clear(); + _vector = controlpoints; + controlpoints.clear(); + write_to_SVG(); + return _vector; + } } + return controlpoints; } float PowerStrokePointArrayParam::median_width() diff --git a/src/live_effects/parameter/powerstrokepointarray.h b/src/live_effects/parameter/powerstrokepointarray.h index b8e63e5f7..a1d4db3ca 100644 --- a/src/live_effects/parameter/powerstrokepointarray.h +++ b/src/live_effects/parameter/powerstrokepointarray.h @@ -47,7 +47,7 @@ public: Geom::Piecewise > const & get_pwd2_normal() const { return last_pwd2_normal; } void recalculate_controlpoints_for_new_pwd2(Geom::Piecewise > const & pwd2_in); - void reverse_controlpoints(); + std::vector reverse_controlpoints(bool write); void set_scale_width(double scale_width){_scale_width = scale_width;}; double _scale_width; friend class PowerStrokePointArrayParamKnotHolderEntity; -- cgit v1.2.3 From 2930567e3fed1875a3c1d903634b865b135ea6ef Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Date: Wed, 29 Nov 2017 15:26:56 +0100 Subject: Add base interpolator parameter --- src/live_effects/lpe-powerstroke.cpp | 209 +++++++++++++++++++++++++++++------ src/live_effects/lpe-powerstroke.h | 3 +- 2 files changed, 175 insertions(+), 37 deletions(-) (limited to 'src/live_effects') diff --git a/src/live_effects/lpe-powerstroke.cpp b/src/live_effects/lpe-powerstroke.cpp index 51c8451a5..96f487211 100644 --- a/src/live_effects/lpe-powerstroke.cpp +++ b/src/live_effects/lpe-powerstroke.cpp @@ -164,6 +164,7 @@ static const Util::EnumDataConverter LineJoinTypeConverter(LineJoinTyp LPEPowerStroke::LPEPowerStroke(LivePathEffectObject *lpeobject) : Effect(lpeobject), offset_points(_("Offset points"), _("Offset points"), "offset_points", &wr, this), + interpolate_original(_("Interpolate original"), _("Interpolate original path"), "interpolate_original", &wr, this, false), sort_points(_("Sort points"), _("Sort offset points according to their time value along the curve"), "sort_points", &wr, this, true), interpolator_type(_("Interpolator type:"), _("Determines which kind of interpolator will be used to interpolate between stroke width along the path"), "interpolator_type", InterpolatorTypeConverter, &wr, this, Geom::Interpolate::INTERP_CUBICBEZIER), interpolator_beta(_("Smoothness:"), _("Sets the smoothness for the CubicBezierJohan interpolator; 0 = linear interpolation, 1 = smooth"), "interpolator_beta", &wr, this, 0.2), @@ -182,6 +183,7 @@ LPEPowerStroke::LPEPowerStroke(LivePathEffectObject *lpeobject) : registerParameter(&offset_points); registerParameter(&sort_points); + registerParameter(&interpolate_original); registerParameter(&interpolator_type); registerParameter(&interpolator_beta); registerParameter(&start_linecap_type); @@ -192,6 +194,7 @@ LPEPowerStroke::LPEPowerStroke(LivePathEffectObject *lpeobject) : scale_width.param_set_range(0.0, Geom::infinity()); scale_width.param_set_increments(0.1, 0.1); scale_width.param_set_digits(4); + interpolate_original_prev = !interpolate_original; } LPEPowerStroke::~LPEPowerStroke() @@ -566,6 +569,42 @@ LPEPowerStroke::doEffect_path (Geom::PathVector const & path_in) return path_out; } Geom::PathVector pathv = pathv_to_linear_and_cubic_beziers(path_in); + // create stroke path where points (x,y) := (t, offset) + + if (interpolate_original) { + Geom::PathVector path_out; + for(Geom::PathVector::const_iterator path_it = path_in.begin(); path_it != path_in.end(); ++path_it) { + if (path_it->empty()) + continue; + + if (path_it->closed()) { + g_warning("Interpolate points LPE currently ignores whether path is closed or not."); + } + std::vector pts; + pts.push_back(path_it->initialPoint()); + + for (Geom::Path::const_iterator it = path_it->begin(), e = path_it->end_default(); it != e; ++it) { + pts.push_back((*it).finalPoint()); + } + //We use this fixed interpolator to simplfy the UI and for better results + Geom::Interpolate::Interpolator *interpolator = Geom::Interpolate::Interpolator::create(Geom::Interpolate::INTERP_CENTRIPETAL_CATMULLROM); + Geom::Path path = interpolator->interpolateToPath(pts); + + path_out.push_back(path); + } + pathv = path_out; + } + Geom::Interpolate::Interpolator *interpolator = Geom::Interpolate::Interpolator::create(static_cast(interpolator_type.get_value())); + if (Geom::Interpolate::CubicBezierJohan *johan = dynamic_cast(interpolator)) { + johan->setBeta(interpolator_beta); + } + if (Geom::Interpolate::CubicBezierSmooth *smooth = dynamic_cast(interpolator)) { + smooth->setBeta(interpolator_beta); + } + if (interpolate_original_prev != interpolate_original) { + adjustForNewPath(pathv); + interpolate_original_prev = interpolate_original; + } Geom::Piecewise > pwd2_in = pathv[0].toPwSb(); Piecewise > der = derivative(pwd2_in); Piecewise > n = unitVector(der,0.0001); @@ -609,18 +648,116 @@ LPEPowerStroke::doEffect_path (Geom::PathVector const & path_in) // instead of the heavily compressed coordinate system of (segment_no offset, Y) in which the knots are stored double pwd2_in_arclength = length(pwd2_in); double xcoord_scaling = pwd2_in_arclength / ts.back()[Geom::X]; - for (std::size_t i = 0, e = ts.size(); i < e; ++i) { - ts[i][Geom::X] *= xcoord_scaling; + if (interpolate_original) { + size_t i = 0; + std::vector ts_aprox; + size_t steps = 0; + double distance = 0; + Geom::PathVector splits; + Geom::Coord start = 0; + for(std::vector::iterator point = ts.begin(); point != ts.end();) { + point++; + Geom::Coord end = (*point)[Geom::X]; + if (Geom::are_near(start, end,0.0001)) { + continue; + } + splits.push_back(path_in[0].portion(start, end)); + start = end; + if (end == pathv[0].size()) { + break; + } + } + size_t counter = 0; + for(Geom::PathVector::const_iterator path_it = splits.begin(); path_it != splits.end(); ++path_it) { + if (path_it->empty()) { + continue; + } + Geom::Piecewise > path_pwd = (*path_it).toPwSb(); + size_t size = (*path_it).size(); + double path_it_arclength = length(path_pwd); + Geom::Point start = ts[counter]; + counter++; + Geom::Point end = ts[counter]; + if (Geom::are_near(start[Geom::Y],end[Geom::Y],0.0001)) { + continue; + } + double gap = (start[Geom::Y] - end[Geom::Y])/size; + double width = 0; + width = start[Geom::Y]; + for (size_t j = 1; j < size; j++){ + Geom::Path current_curve = (*path_it).portion(j-1, j); + double path_it_arclength_sub = length(current_curve.toPwSb()); + double factor = path_it_arclength_sub * size/path_it_arclength; + width -= gap * factor; + ts.push_back(Geom::Point(std::floor(ts[counter-1][Geom::X]) + j, width)); + } + } + sort(ts.begin(), ts.end(), compare_offsets); } // create stroke path where points (x,y) := (t, offset) - Geom::Interpolate::Interpolator *interpolator = Geom::Interpolate::Interpolator::create(static_cast(interpolator_type.get_value())); - if (Geom::Interpolate::CubicBezierJohan *johan = dynamic_cast(interpolator)) { - johan->setBeta(interpolator_beta); - } - if (Geom::Interpolate::CubicBezierSmooth *smooth = dynamic_cast(interpolator)) { - smooth->setBeta(interpolator_beta); + + Geom::Path fixed_path; + Geom::Path fixed_mirrorpath; + Geom::Path strokepath; + if (interpolate_original) { + std::vector ts_normal; + std::vector ts_mirror; + + bool previous_isnode = false; + size_t counter = 0; + for(auto point:ts) { + Geom::Point normal_pos = pwd2_in.valueAt(point[Geom::X]) + (point[Geom::Y] * scale_width) * n.valueAt(point[Geom::X]); + Geom::Point mirror_pos = pwd2_in.valueAt(point[Geom::X]) + (point[Geom::Y] * -1 * scale_width) * n.valueAt(point[Geom::X]); + Geom::Point normal = Geom::Point(normal_pos[Geom::X] * xcoord_scaling, normal_pos[Geom::Y]); + Geom::Point mirror = Geom::Point(mirror_pos [Geom::X] * xcoord_scaling, mirror_pos [Geom::Y]); + //a bit smoothig tweak + if (counter > 2) { + Geom::Point granparent_normal = ts_normal[counter-2]; + Geom::Point parent_normal = ts_normal[counter-1]; + Geom::Point granparent_mirror = ts_mirror [counter-2]; + Geom::Point parent_mirror = ts_mirror [counter-1]; + bool isnode = ts[counter][Geom::X] == std::floor(ts[counter ][Geom::X]); + bool previous_isnode = ts[counter-1][Geom::X] == std::floor(ts[counter-1][Geom::X]); + bool ccw_toggle_normal = cross(parent_normal - granparent_normal, normal - granparent_normal) < 0; + bool ccw_toggle_mirror = cross(parent_mirror - granparent_mirror , mirror - granparent_mirror ) < 0; + Geom::Ray ray_normal_a(parent_normal, granparent_normal); + Geom::Ray ray_normal_b(parent_normal , normal); + Geom::Ray ray_mirror_a (parent_mirror, granparent_mirror); + Geom::Ray ray_mirror_b (parent_mirror , mirror); + double angle_normal = angle_between(ray_normal_a, ray_normal_b, ccw_toggle_normal); + double angle_mirror = angle_between(ray_mirror_a , ray_mirror_b , ccw_toggle_mirror); + if (point[Geom::X] > 2 && + previous_isnode && + !isnode && + !ccw_toggle_normal && + angle_normal < Geom::rad_from_deg(90)) + { + ts_normal.pop_back(); + } + if (point[Geom::X] > 2 && + previous_isnode && + !isnode && + ccw_toggle_mirror && + angle_mirror < Geom::rad_from_deg(90)) + { + ts_mirror.pop_back(); + } + } + ts_normal.push_back(normal); + ts_mirror.push_back(mirror); + counter++; + } + fixed_path = interpolator->interpolateToPath(ts_normal); + fixed_path *= Scale(1/xcoord_scaling, 1); + fixed_mirrorpath = interpolator->interpolateToPath(ts_mirror); + fixed_mirrorpath *= Scale(1/xcoord_scaling, 1); + fixed_mirrorpath = fixed_mirrorpath.reversed(); + } else { + for (std::size_t i = 0, e = ts.size(); i < e; ++i) { + ts[i][Geom::X] *= xcoord_scaling; + } + strokepath = interpolator->interpolateToPath(ts); } - Geom::Path strokepath = interpolator->interpolateToPath(ts); delete interpolator; // apply the inverse knot-xcoord scaling that was applied before the interpolation @@ -638,13 +775,13 @@ LPEPowerStroke::doEffect_path (Geom::PathVector const & path_in) y = portion(y, rtsmin.at(0), rtsmax.at(0)); } - LineJoinType jointype = static_cast(linejoin_type.get_value()); - - Piecewise > pwd2_out = compose(pwd2_in,x) + y*compose(n,x); - Piecewise > mirrorpath = reverse( compose(pwd2_in,x) - y*compose(n,x)); - - Geom::Path fixed_path = path_from_piecewise_fix_cusps( pwd2_out, y, jointype, miter_limit, LPE_CONVERSION_TOLERANCE); - Geom::Path fixed_mirrorpath = path_from_piecewise_fix_cusps( mirrorpath, reverse(y), jointype, miter_limit, LPE_CONVERSION_TOLERANCE); + if (!interpolate_original) { + LineJoinType jointype = static_cast(linejoin_type.get_value()); + Piecewise > pwd2_out = compose(pwd2_in,x) + y*compose(n,x); + Piecewise > mirrorpath = reverse( compose(pwd2_in,x) - y*compose(n,x)); + fixed_path = path_from_piecewise_fix_cusps( pwd2_out, y, jointype, miter_limit, LPE_CONVERSION_TOLERANCE); + fixed_mirrorpath = path_from_piecewise_fix_cusps( mirrorpath, reverse(y), jointype, miter_limit, LPE_CONVERSION_TOLERANCE); + } if (pathv[0].closed()) { fixed_path.close(true); path_out.push_back(fixed_path); @@ -659,31 +796,31 @@ LPEPowerStroke::doEffect_path (Geom::PathVector const & path_in) case LINECAP_PEAK: { Geom::Point end_deriv = -unitTangentAt( reverse(pwd2_in.segs.back()), 0.); - double radius = 0.5 * distance(pwd2_out.lastValue(), mirrorpath.firstValue()); - Geom::Point midpoint = 0.5*(pwd2_out.lastValue() + mirrorpath.firstValue()) + radius*end_deriv; + double radius = 0.5 * distance(fixed_path.finalPoint(), fixed_mirrorpath.initialPoint()); + Geom::Point midpoint = 0.5*(fixed_path.finalPoint() + fixed_mirrorpath.initialPoint()) + radius*end_deriv; fixed_path.appendNew(midpoint); - fixed_path.appendNew(mirrorpath.firstValue()); + fixed_path.appendNew(fixed_mirrorpath.initialPoint()); break; } case LINECAP_SQUARE: { Geom::Point end_deriv = -unitTangentAt( reverse(pwd2_in.segs.back()), 0.); - double radius = 0.5 * distance(pwd2_out.lastValue(), mirrorpath.firstValue()); - fixed_path.appendNew( pwd2_out.lastValue() + radius*end_deriv ); - fixed_path.appendNew( mirrorpath.firstValue() + radius*end_deriv ); - fixed_path.appendNew( mirrorpath.firstValue() ); + double radius = 0.5 * distance(fixed_path.finalPoint(), fixed_mirrorpath.initialPoint()); + fixed_path.appendNew( fixed_path.finalPoint() + radius*end_deriv ); + fixed_path.appendNew( fixed_mirrorpath.initialPoint() + radius*end_deriv ); + fixed_path.appendNew( fixed_mirrorpath.initialPoint() ); break; } case LINECAP_BUTT: { - fixed_path.appendNew( mirrorpath.firstValue() ); + fixed_path.appendNew( fixed_mirrorpath.initialPoint() ); break; } case LINECAP_ROUND: default: { - double radius1 = 0.5 * distance(pwd2_out.lastValue(), mirrorpath.firstValue()); - fixed_path.appendNew( radius1, radius1, M_PI/2., false, y.lastValue() < 0, mirrorpath.firstValue() ); + double radius1 = 0.5 * distance(fixed_path.finalPoint(), fixed_mirrorpath.initialPoint()); + fixed_path.appendNew( radius1, radius1, M_PI/2., false, y.lastValue() < 0, fixed_mirrorpath.initialPoint() ); break; } } @@ -696,31 +833,31 @@ LPEPowerStroke::doEffect_path (Geom::PathVector const & path_in) case LINECAP_PEAK: { Geom::Point start_deriv = unitTangentAt( pwd2_in.segs.front(), 0.); - double radius = 0.5 * distance(pwd2_out.firstValue(), mirrorpath.lastValue()); - Geom::Point midpoint = 0.5*(mirrorpath.lastValue() + pwd2_out.firstValue()) - radius*start_deriv; + double radius = 0.5 * distance(fixed_path.initialPoint(), fixed_mirrorpath.finalPoint()); + Geom::Point midpoint = 0.5*(fixed_mirrorpath.finalPoint() + fixed_path.initialPoint()) - radius*start_deriv; fixed_path.appendNew( midpoint ); - fixed_path.appendNew( pwd2_out.firstValue() ); + fixed_path.appendNew( fixed_path.initialPoint() ); break; } case LINECAP_SQUARE: { Geom::Point start_deriv = unitTangentAt( pwd2_in.segs.front(), 0.); - double radius = 0.5 * distance(pwd2_out.firstValue(), mirrorpath.lastValue()); - fixed_path.appendNew( mirrorpath.lastValue() - radius*start_deriv ); - fixed_path.appendNew( pwd2_out.firstValue() - radius*start_deriv ); - fixed_path.appendNew( pwd2_out.firstValue() ); + double radius = 0.5 * distance(fixed_path.initialPoint(), fixed_mirrorpath.finalPoint()); + fixed_path.appendNew( fixed_mirrorpath.finalPoint() - radius*start_deriv ); + fixed_path.appendNew( fixed_path.initialPoint() - radius*start_deriv ); + fixed_path.appendNew( fixed_path.initialPoint() ); break; } case LINECAP_BUTT: { - fixed_path.appendNew( pwd2_out.firstValue() ); + fixed_path.appendNew( fixed_path.initialPoint() ); break; } case LINECAP_ROUND: default: { - double radius2 = 0.5 * distance(pwd2_out.firstValue(), mirrorpath.lastValue()); - fixed_path.appendNew( radius2, radius2, M_PI/2., false, y.firstValue() < 0, pwd2_out.firstValue() ); + double radius2 = 0.5 * distance(fixed_path.initialPoint(), fixed_mirrorpath.finalPoint()); + fixed_path.appendNew( radius2, radius2, M_PI/2., false, y.firstValue() < 0, fixed_path.initialPoint() ); break; } } diff --git a/src/live_effects/lpe-powerstroke.h b/src/live_effects/lpe-powerstroke.h index 4a0eda75a..53aab1b05 100644 --- a/src/live_effects/lpe-powerstroke.h +++ b/src/live_effects/lpe-powerstroke.h @@ -38,6 +38,7 @@ public: private: BoolParam sort_points; + BoolParam interpolate_original; EnumParam interpolator_type; ScalarParam interpolator_beta; ScalarParam scale_width; @@ -45,7 +46,7 @@ private: EnumParam linejoin_type; ScalarParam miter_limit; EnumParam end_linecap_type; - + bool interpolate_original_prev; LPEPowerStroke(const LPEPowerStroke&); LPEPowerStroke& operator=(const LPEPowerStroke&); }; -- cgit v1.2.3 From cd56d55f26a8c9029de91924d0ab827ad877713d Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Date: Wed, 29 Nov 2017 15:34:49 +0100 Subject: Add BSPLine interpolator --- src/live_effects/lpe-interpolate_points.cpp | 3 +- src/live_effects/lpe-powerstroke-interpolators.h | 37 +++++++++++++++++++++++- src/live_effects/lpe-powerstroke.cpp | 3 +- 3 files changed, 40 insertions(+), 3 deletions(-) (limited to 'src/live_effects') 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..651eba057 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" @@ -27,6 +27,7 @@ enum InterpolatorType { INTERP_LINEAR, INTERP_CUBICBEZIER, INTERP_CUBICBEZIER_JOHAN, + INTERP_BSPLINE, INTERP_SPIRO, INTERP_CUBICBEZIER_SMOOTH, INTERP_CENTRIPETAL_CATMULLROM @@ -65,6 +66,38 @@ 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) ); + for (unsigned int i = 1 ; i < points.size(); ++i) { + Geom::Point pointA = points.at(i-1); + Geom::Point pointB = points.at(i); + Geom::Ray ray(pointA, pointB); + double angle = ray.angle(); + if (angle == 0) { + continue; + } + std::cout << angle << "angle" << std::endl; + double k1 = (Geom::distance(pointA, pointB)*std::sin(angle))/2.0; + std::cout << k1 << "k1" << std::endl; + std::cout << std::sin(angle) << "std::sin(angle)" << std::endl; + Geom::Point handle_1 = Geom::Point::polar(angle, k1) + pointA; + Geom::Point handle_2 = Geom::Point::polar(angle, k1 * 2) + pointA; + path.appendNew(handle_1, handle_2, pointB); + } + return path; + }; + +private: + BSpline(const BSpline&); + BSpline& operator=(const BSpline&); +}; + // this class is terrible class CubicBezierFit : public Interpolator { public: @@ -302,6 +335,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 96f487211..b2b55a08c 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 From 9599c53b48cbd737cf4c95120f0eb654dfce7b74 Mon Sep 17 00:00:00 2001 From: Jabiertxo Arraiza Cenoz Date: Wed, 29 Nov 2017 22:40:27 +0100 Subject: Working with BSPline interpolator --- src/live_effects/lpe-powerstroke-interpolators.h | 26 ++++++++++-------------- 1 file changed, 11 insertions(+), 15 deletions(-) (limited to 'src/live_effects') diff --git a/src/live_effects/lpe-powerstroke-interpolators.h b/src/live_effects/lpe-powerstroke-interpolators.h index 651eba057..baa341fcb 100644 --- a/src/live_effects/lpe-powerstroke-interpolators.h +++ b/src/live_effects/lpe-powerstroke-interpolators.h @@ -74,21 +74,17 @@ public: virtual Path interpolateToPath(std::vector const &points) const { Path path; path.start( points.at(0) ); - for (unsigned int i = 1 ; i < points.size(); ++i) { - Geom::Point pointA = points.at(i-1); - Geom::Point pointB = points.at(i); - Geom::Ray ray(pointA, pointB); - double angle = ray.angle(); - if (angle == 0) { - continue; - } - std::cout << angle << "angle" << std::endl; - double k1 = (Geom::distance(pointA, pointB)*std::sin(angle))/2.0; - std::cout << k1 << "k1" << std::endl; - std::cout << std::sin(angle) << "std::sin(angle)" << std::endl; - Geom::Point handle_1 = Geom::Point::polar(angle, k1) + pointA; - Geom::Point handle_2 = Geom::Point::polar(angle, k1 * 2) + pointA; - path.appendNew(handle_1, handle_2, pointB); + Geom::Point handle_prev = points.at(0); + for (unsigned int i = 1 ; i < points.size() - 2; ++i) { + Geom::Line line_a(points.at(i), points.at(i+1)); + Geom::Line line_b(points.at(i+1), points.at(i+2)); + Geom::Point handle_next_tmp = line_a.pointAt(line_a.nearestTime(points.at(i-1))); + Geom::Point handle_next = line_b.pointAt(line_b.nearestTime(handle_next_tmp)); + Geom::Line line_handles(handle_next, points.at(i-1)); + double angle = line_handles.angle(); + Geom::Point handle_2 = Geom::Point::polar(angle, Geom::distance(handle_next,points.at(i))) + handle_next; + path.appendNew(handle_prev, handle_2, points.at(i)); + handle_prev = handle_next; } return path; }; -- cgit v1.2.3 From 524ed2d90dbea0b3be40c0786b4200bf3f6a146c Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Date: Thu, 30 Nov 2017 02:26:02 +0100 Subject: Working bspline, to fine tune --- src/live_effects/lpe-powerstroke-interpolators.h | 41 ++++++++++++++++++------ 1 file changed, 32 insertions(+), 9 deletions(-) (limited to 'src/live_effects') diff --git a/src/live_effects/lpe-powerstroke-interpolators.h b/src/live_effects/lpe-powerstroke-interpolators.h index baa341fcb..21d25a797 100644 --- a/src/live_effects/lpe-powerstroke-interpolators.h +++ b/src/live_effects/lpe-powerstroke-interpolators.h @@ -74,18 +74,41 @@ public: virtual Path interpolateToPath(std::vector const &points) const { Path path; path.start( points.at(0) ); + Geom::Point handle_1(0,0); Geom::Point handle_prev = points.at(0); - for (unsigned int i = 1 ; i < points.size() - 2; ++i) { - Geom::Line line_a(points.at(i), points.at(i+1)); - Geom::Line line_b(points.at(i+1), points.at(i+2)); - Geom::Point handle_next_tmp = line_a.pointAt(line_a.nearestTime(points.at(i-1))); - Geom::Point handle_next = line_b.pointAt(line_b.nearestTime(handle_next_tmp)); - Geom::Line line_handles(handle_next, points.at(i-1)); - double angle = line_handles.angle(); - Geom::Point handle_2 = Geom::Point::polar(angle, Geom::distance(handle_next,points.at(i))) + handle_next; + for (unsigned int i = 1 ; i < points.size() - 1; ++i) { + Geom::Line line_a(points.at(i - 1), points.at(i)); + double angle_a = line_a.angle(); + Geom::Line line_b(points.at(i),points.at(i + 1)); + double angle_b = line_b.angle(); + Geom::Line line_handles(line_a.pointAt(0.66667),line_b.pointAt(0.33334)); + line_handles *= Geom::Translate(points.at(i) - line_handles.pointAt(0.5)); + Geom::Line line_perp_a(line_a.pointAt(0.5), Geom::Point::polar(angle_a + Geom::rad_from_deg(90),1) +line_a.pointAt(0.5)); + Geom::Line line_perp_b(line_b.pointAt(0.5), Geom::Point::polar(angle_b + Geom::rad_from_deg(90),1) +line_b.pointAt(0.5)); + std::vector result = line_perp_a.intersect(line_perp_b); + Geom::Point handle_2(0,0); + if(result.size() > 0) { + Geom::Line line_to_handle_a(result[0],line_a.pointAt(0.66667)); + Geom::Line line_to_handle_b(result[0],line_b.pointAt(0.33334)); + std::vector handle_a_res = line_to_handle_a.intersect(line_handles); + std::vector handle_b_res = line_to_handle_b.intersect(line_handles); + if(handle_a_res.size() > 0) { + handle_2 = handle_a_res[0]; + } + if(handle_a_res.size() > 0) { + handle_1 = handle_b_res[0]; + } + } + if (i == 1) { + Geom::Line start_segment(handle_prev,handle_2); + handle_prev = start_segment.pointAt(0.5); + } path.appendNew(handle_prev, handle_2, points.at(i)); - handle_prev = handle_next; + handle_prev = handle_1; } + Geom::Point last = points.at(points.size()-1); + Geom::Line last_segment(last,handle_1); + path.appendNew(handle_1, last_segment.pointAt(0.5), last); return path; }; -- cgit v1.2.3 From 67f654a049a12eb86b0e2f137212a50407b8e82e Mon Sep 17 00:00:00 2001 From: Jabiertxo Arraiza Cenoz Date: Fri, 1 Dec 2017 20:21:25 +0100 Subject: Add show handles --- src/live_effects/lpe-show_handles.cpp | 23 +++++++++++++++++++++-- src/live_effects/lpe-show_handles.h | 1 + 2 files changed, 22 insertions(+), 2 deletions(-) (limited to 'src/live_effects') diff --git a/src/live_effects/lpe-show_handles.cpp b/src/live_effects/lpe-show_handles.cpp index 7c298d0e7..2da570537 100644 --- a/src/live_effects/lpe-show_handles.cpp +++ b/src/live_effects/lpe-show_handles.cpp @@ -12,6 +12,7 @@ #include <2geom/svg-path-parser.h> #include "helper/geom.h" #include "desktop-style.h" +#include "display/curve.h" #include "style.h" #include "svg/svg.h" @@ -27,12 +28,14 @@ LPEShowHandles::LPEShowHandles(LivePathEffectObject *lpeobject) handles(_("Show handles"), _("Show handles"), "handles", &wr, this, true), original_path(_("Show path"), _("Show path"), "original_path", &wr, this, true), show_center_node(_("Show center of node"), _("Show center of node"), "show_center_node", &wr, this, false), + original_d(_("Show original"), _("Show original"), "original_d", &wr, this, false), scale_nodes_and_handles(_("Scale nodes and handles"), _("Scale nodes and handles"), "scale_nodes_and_handles", &wr, this, 10) { registerParameter(&nodes); registerParameter(&handles); registerParameter(&original_path); registerParameter(&show_center_node); + registerParameter(&original_d); registerParameter(&scale_nodes_and_handles); scale_nodes_and_handles.param_set_range(0, 500.); scale_nodes_and_handles.param_set_increments(1, 1); @@ -80,7 +83,7 @@ void LPEShowHandles::doBeforeEffect (SPLPEItem const* lpeitem) Geom::PathVector LPEShowHandles::doEffect_path (Geom::PathVector const & path_in) { Geom::PathVector path_out; - Geom::PathVector const original_pathv = pathv_to_linear_and_cubic_beziers(path_in); + Geom::PathVector original_pathv = pathv_to_linear_and_cubic_beziers(path_in); if(original_path) { for (unsigned int i=0; i < path_in.size(); i++) { path_out.push_back(path_in[i]); @@ -89,10 +92,26 @@ Geom::PathVector LPEShowHandles::doEffect_path (Geom::PathVector const & path_in if(!outline_path.empty()) { outline_path.clear(); } - generateHelperPath(original_pathv); + if (original_d) { + SPCurve * shape_curve = sp_shape->getCurveBeforeLPE(); + if (shape_curve) { + Geom::PathVector original_curve = shape_curve->get_pathvector(); + if(original_path) { + for (unsigned int i=0; i < original_curve.size(); i++) { + path_out.push_back(original_curve[i]); + } + } + original_pathv.insert(original_pathv.end(), original_curve.begin(), original_curve.end()); + } + generateHelperPath(original_pathv); + shape_curve->unref(); + } else { + generateHelperPath(original_pathv); + } for (unsigned int i=0; i < outline_path.size(); i++) { path_out.push_back(outline_path[i]); } + return path_out; } diff --git a/src/live_effects/lpe-show_handles.h b/src/live_effects/lpe-show_handles.h index c46abd2c2..583be9e61 100644 --- a/src/live_effects/lpe-show_handles.h +++ b/src/live_effects/lpe-show_handles.h @@ -43,6 +43,7 @@ private: BoolParam nodes; BoolParam handles; BoolParam original_path; + BoolParam original_d; BoolParam show_center_node; ScalarParam scale_nodes_and_handles; double stroke_width; -- cgit v1.2.3 From cbdd1dfb6d9e228c82905cc5032eef81164887d6 Mon Sep 17 00:00:00 2001 From: Jabiertxo Arraiza Cenoz Date: Fri, 1 Dec 2017 20:54:29 +0100 Subject: Remobe BSPline interpolator, a non success code and remove showhandles code --- src/live_effects/lpe-interpolate_points.cpp | 3 +- src/live_effects/lpe-powerstroke-interpolators.h | 56 +----------------------- src/live_effects/lpe-powerstroke.cpp | 3 +- src/live_effects/lpe-show_handles.cpp | 23 +--------- src/live_effects/lpe-show_handles.h | 1 - 5 files changed, 5 insertions(+), 81 deletions(-) (limited to 'src/live_effects') diff --git a/src/live_effects/lpe-interpolate_points.cpp b/src/live_effects/lpe-interpolate_points.cpp index c745921c2..7d4c88dc1 100644 --- a/src/live_effects/lpe-interpolate_points.cpp +++ b/src/live_effects/lpe-interpolate_points.cpp @@ -25,8 +25,7 @@ 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_BSPLINE , N_("BSpline"), "BSpline"} + {Geom::Interpolate::INTERP_CENTRIPETAL_CATMULLROM, N_("Centripetal Catmull-Rom"), "CentripetalCatmullRom"} }; 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 21d25a797..e3ab37e27 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" @@ -27,7 +27,6 @@ enum InterpolatorType { INTERP_LINEAR, INTERP_CUBICBEZIER, INTERP_CUBICBEZIER_JOHAN, - INTERP_BSPLINE, INTERP_SPIRO, INTERP_CUBICBEZIER_SMOOTH, INTERP_CENTRIPETAL_CATMULLROM @@ -66,57 +65,6 @@ 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 handle_1(0,0); - Geom::Point handle_prev = points.at(0); - for (unsigned int i = 1 ; i < points.size() - 1; ++i) { - Geom::Line line_a(points.at(i - 1), points.at(i)); - double angle_a = line_a.angle(); - Geom::Line line_b(points.at(i),points.at(i + 1)); - double angle_b = line_b.angle(); - Geom::Line line_handles(line_a.pointAt(0.66667),line_b.pointAt(0.33334)); - line_handles *= Geom::Translate(points.at(i) - line_handles.pointAt(0.5)); - Geom::Line line_perp_a(line_a.pointAt(0.5), Geom::Point::polar(angle_a + Geom::rad_from_deg(90),1) +line_a.pointAt(0.5)); - Geom::Line line_perp_b(line_b.pointAt(0.5), Geom::Point::polar(angle_b + Geom::rad_from_deg(90),1) +line_b.pointAt(0.5)); - std::vector result = line_perp_a.intersect(line_perp_b); - Geom::Point handle_2(0,0); - if(result.size() > 0) { - Geom::Line line_to_handle_a(result[0],line_a.pointAt(0.66667)); - Geom::Line line_to_handle_b(result[0],line_b.pointAt(0.33334)); - std::vector handle_a_res = line_to_handle_a.intersect(line_handles); - std::vector handle_b_res = line_to_handle_b.intersect(line_handles); - if(handle_a_res.size() > 0) { - handle_2 = handle_a_res[0]; - } - if(handle_a_res.size() > 0) { - handle_1 = handle_b_res[0]; - } - } - if (i == 1) { - Geom::Line start_segment(handle_prev,handle_2); - handle_prev = start_segment.pointAt(0.5); - } - path.appendNew(handle_prev, handle_2, points.at(i)); - handle_prev = handle_1; - } - Geom::Point last = points.at(points.size()-1); - Geom::Line last_segment(last,handle_1); - path.appendNew(handle_1, 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: @@ -354,8 +302,6 @@ 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 b2b55a08c..96f487211 100644 --- a/src/live_effects/lpe-powerstroke.cpp +++ b/src/live_effects/lpe-powerstroke.cpp @@ -123,8 +123,7 @@ 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_BSPLINE , N_("BSpline"), "BSpline"} + {Geom::Interpolate::INTERP_CENTRIPETAL_CATMULLROM, N_("Centripetal Catmull-Rom"), "CentripetalCatmullRom"} }; static const Util::EnumDataConverter InterpolatorTypeConverter(InterpolatorTypeData, sizeof(InterpolatorTypeData)/sizeof(*InterpolatorTypeData)); diff --git a/src/live_effects/lpe-show_handles.cpp b/src/live_effects/lpe-show_handles.cpp index 2da570537..7c298d0e7 100644 --- a/src/live_effects/lpe-show_handles.cpp +++ b/src/live_effects/lpe-show_handles.cpp @@ -12,7 +12,6 @@ #include <2geom/svg-path-parser.h> #include "helper/geom.h" #include "desktop-style.h" -#include "display/curve.h" #include "style.h" #include "svg/svg.h" @@ -28,14 +27,12 @@ LPEShowHandles::LPEShowHandles(LivePathEffectObject *lpeobject) handles(_("Show handles"), _("Show handles"), "handles", &wr, this, true), original_path(_("Show path"), _("Show path"), "original_path", &wr, this, true), show_center_node(_("Show center of node"), _("Show center of node"), "show_center_node", &wr, this, false), - original_d(_("Show original"), _("Show original"), "original_d", &wr, this, false), scale_nodes_and_handles(_("Scale nodes and handles"), _("Scale nodes and handles"), "scale_nodes_and_handles", &wr, this, 10) { registerParameter(&nodes); registerParameter(&handles); registerParameter(&original_path); registerParameter(&show_center_node); - registerParameter(&original_d); registerParameter(&scale_nodes_and_handles); scale_nodes_and_handles.param_set_range(0, 500.); scale_nodes_and_handles.param_set_increments(1, 1); @@ -83,7 +80,7 @@ void LPEShowHandles::doBeforeEffect (SPLPEItem const* lpeitem) Geom::PathVector LPEShowHandles::doEffect_path (Geom::PathVector const & path_in) { Geom::PathVector path_out; - Geom::PathVector original_pathv = pathv_to_linear_and_cubic_beziers(path_in); + Geom::PathVector const original_pathv = pathv_to_linear_and_cubic_beziers(path_in); if(original_path) { for (unsigned int i=0; i < path_in.size(); i++) { path_out.push_back(path_in[i]); @@ -92,26 +89,10 @@ Geom::PathVector LPEShowHandles::doEffect_path (Geom::PathVector const & path_in if(!outline_path.empty()) { outline_path.clear(); } - if (original_d) { - SPCurve * shape_curve = sp_shape->getCurveBeforeLPE(); - if (shape_curve) { - Geom::PathVector original_curve = shape_curve->get_pathvector(); - if(original_path) { - for (unsigned int i=0; i < original_curve.size(); i++) { - path_out.push_back(original_curve[i]); - } - } - original_pathv.insert(original_pathv.end(), original_curve.begin(), original_curve.end()); - } - generateHelperPath(original_pathv); - shape_curve->unref(); - } else { - generateHelperPath(original_pathv); - } + generateHelperPath(original_pathv); for (unsigned int i=0; i < outline_path.size(); i++) { path_out.push_back(outline_path[i]); } - return path_out; } diff --git a/src/live_effects/lpe-show_handles.h b/src/live_effects/lpe-show_handles.h index 583be9e61..c46abd2c2 100644 --- a/src/live_effects/lpe-show_handles.h +++ b/src/live_effects/lpe-show_handles.h @@ -43,7 +43,6 @@ private: BoolParam nodes; BoolParam handles; BoolParam original_path; - BoolParam original_d; BoolParam show_center_node; ScalarParam scale_nodes_and_handles; double stroke_width; -- cgit v1.2.3 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/live_effects') 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 From b95f5438b75deffac0e8780857733257e21b1f68 Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Date: Sat, 2 Dec 2017 11:51:39 +0100 Subject: Remobing bspline interpolator --- src/live_effects/lpe-interpolate_points.cpp | 3 +- src/live_effects/lpe-powerstroke-interpolators.h | 78 +----------------------- src/live_effects/lpe-powerstroke.cpp | 9 ++- 3 files changed, 7 insertions(+), 83 deletions(-) (limited to 'src/live_effects') diff --git a/src/live_effects/lpe-interpolate_points.cpp b/src/live_effects/lpe-interpolate_points.cpp index c745921c2..7d4c88dc1 100644 --- a/src/live_effects/lpe-interpolate_points.cpp +++ b/src/live_effects/lpe-interpolate_points.cpp @@ -25,8 +25,7 @@ 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_BSPLINE , N_("BSpline"), "BSpline"} + {Geom::Interpolate::INTERP_CENTRIPETAL_CATMULLROM, N_("Centripetal Catmull-Rom"), "CentripetalCatmullRom"} }; 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 0c1b60754..e3ab37e27 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,8 +29,7 @@ enum InterpolatorType { INTERP_CUBICBEZIER_JOHAN, INTERP_SPIRO, INTERP_CUBICBEZIER_SMOOTH, - INTERP_CENTRIPETAL_CATMULLROM, - INTERP_BSPLINE + INTERP_CENTRIPETAL_CATMULLROM }; class Interpolator { @@ -66,77 +65,6 @@ 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: @@ -374,8 +302,6 @@ 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 47543107b..f4e4a06ca 100644 --- a/src/live_effects/lpe-powerstroke.cpp +++ b/src/live_effects/lpe-powerstroke.cpp @@ -123,8 +123,7 @@ 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_BSPLINE , N_("BSpline"), "BSpline"} + {Geom::Interpolate::INTERP_CENTRIPETAL_CATMULLROM, N_("Centripetal Catmull-Rom"), "CentripetalCatmullRom"} }; static const Util::EnumDataConverter InterpolatorTypeConverter(InterpolatorTypeData, sizeof(InterpolatorTypeData)/sizeof(*InterpolatorTypeData)); @@ -165,8 +164,8 @@ static const Util::EnumDataConverter LineJoinTypeConverter(LineJoinTyp LPEPowerStroke::LPEPowerStroke(LivePathEffectObject *lpeobject) : Effect(lpeobject), offset_points(_("Offset points"), _("Offset points"), "offset_points", &wr, this), - interpolate_original(_("Interpolate original"), _("Interpolate original path"), "interpolate_original", &wr, this, false), sort_points(_("Sort points"), _("Sort offset points according to their time value along the curve"), "sort_points", &wr, this, true), + interpolate_original(_("Interpolate original"), _("Interpolate original path"), "interpolate_original", &wr, this, false), interpolator_type(_("Interpolator type:"), _("Determines which kind of interpolator will be used to interpolate between stroke width along the path"), "interpolator_type", InterpolatorTypeConverter, &wr, this, Geom::Interpolate::INTERP_CUBICBEZIER), interpolator_beta(_("Smoothness:"), _("Sets the smoothness for the CubicBezierJohan interpolator; 0 = linear interpolation, 1 = smooth"), "interpolator_beta", &wr, this, 0.2), scale_width(_("Width scale:"), _("Width scale all points"), "scale_width", &wr, this, 1.0), @@ -706,7 +705,7 @@ LPEPowerStroke::doEffect_path (Geom::PathVector const & path_in) Geom::Path fixed_path; Geom::Path fixed_mirrorpath; Geom::Path strokepath; - if (interpolate_original) { + if (interpolate_original && 2==1) { std::vector ts_normal; std::vector ts_mirror; @@ -782,7 +781,7 @@ LPEPowerStroke::doEffect_path (Geom::PathVector const & path_in) y = portion(y, rtsmin.at(0), rtsmax.at(0)); } - if (!interpolate_original) { + if (!interpolate_original || 2>1) { LineJoinType jointype = static_cast(linejoin_type.get_value()); Piecewise > pwd2_out = compose(pwd2_in,x) + y*compose(n,x); Piecewise > mirrorpath = reverse( compose(pwd2_in,x) - y*compose(n,x)); -- cgit v1.2.3 From 3d059a10fd17411f73e88ccde2cd853642ee7dc3 Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Date: Mon, 18 Dec 2017 01:11:36 +0100 Subject: Working on powerstroke fixes to pentool --- src/live_effects/lpe-powerstroke.cpp | 185 +++++------------------------------ src/live_effects/lpe-powerstroke.h | 2 - 2 files changed, 23 insertions(+), 164 deletions(-) (limited to 'src/live_effects') diff --git a/src/live_effects/lpe-powerstroke.cpp b/src/live_effects/lpe-powerstroke.cpp index f4e4a06ca..e7ceaa397 100644 --- a/src/live_effects/lpe-powerstroke.cpp +++ b/src/live_effects/lpe-powerstroke.cpp @@ -97,10 +97,13 @@ static Circle touching_circle( D2 const &curve, double t, double tol=0.0 if ( are_near(L2sq(dM(t)),0.) && (dM[0].size() > 1) && (dM[1].size() > 1) ) { // try second time dM=derivative(dM); } - if ( are_near(L2sq(dM(t)),0.) && (dM[0].size() > 1) && (dM[1].size() > 1) ) { // admit defeat + if ( dM.isZero(tol) || (are_near(L2sq(dM(t)),0.) && (dM[0].size() > 1) && (dM[1].size() > 1) )) { // admit defeat return Geom::Circle(Geom::Point(0., 0.), 0.); } Piecewise > unitv = unitVector(dM,tol); + if (unitv.empty()) { // admit defeat + return Geom::Circle(Geom::Point(0., 0.), 0.); + } Piecewise dMlength = dot(Piecewise >(dM),unitv); Piecewise k = cross(derivative(unitv),unitv); k = divide(k,dMlength,tol,3); @@ -165,7 +168,6 @@ LPEPowerStroke::LPEPowerStroke(LivePathEffectObject *lpeobject) : Effect(lpeobject), offset_points(_("Offset points"), _("Offset points"), "offset_points", &wr, this), sort_points(_("Sort points"), _("Sort offset points according to their time value along the curve"), "sort_points", &wr, this, true), - interpolate_original(_("Interpolate original"), _("Interpolate original path"), "interpolate_original", &wr, this, false), interpolator_type(_("Interpolator type:"), _("Determines which kind of interpolator will be used to interpolate between stroke width along the path"), "interpolator_type", InterpolatorTypeConverter, &wr, this, Geom::Interpolate::INTERP_CUBICBEZIER), interpolator_beta(_("Smoothness:"), _("Sets the smoothness for the CubicBezierJohan interpolator; 0 = linear interpolation, 1 = smooth"), "interpolator_beta", &wr, this, 0.2), scale_width(_("Width scale:"), _("Width scale all points"), "scale_width", &wr, this, 1.0), @@ -183,7 +185,6 @@ LPEPowerStroke::LPEPowerStroke(LivePathEffectObject *lpeobject) : registerParameter(&offset_points); registerParameter(&sort_points); - registerParameter(&interpolate_original); registerParameter(&interpolator_type); registerParameter(&interpolator_beta); registerParameter(&start_linecap_type); @@ -194,7 +195,6 @@ LPEPowerStroke::LPEPowerStroke(LivePathEffectObject *lpeobject) : scale_width.param_set_range(0.0, Geom::infinity()); scale_width.param_set_increments(0.1, 0.1); scale_width.param_set_digits(4); - interpolate_original_prev = !interpolate_original; } LPEPowerStroke::~LPEPowerStroke() @@ -566,57 +566,16 @@ LPEPowerStroke::doEffect_path (Geom::PathVector const & path_in) Geom::PathVector path_out; if (path_in.empty()) { - return path_in; + return path_out; } Geom::PathVector pathv = pathv_to_linear_and_cubic_beziers(path_in); - // create stroke path where points (x,y) := (t, offset) - - if (interpolate_original) { - Geom::PathVector path_out; - for(Geom::PathVector::const_iterator path_it = path_in.begin(); path_it != path_in.end(); ++path_it) { - if (path_it->empty()) - continue; - - if (path_it->closed()) { - g_warning("Interpolate points LPE currently ignores whether path is closed or not."); - } - std::vector pts; - pts.push_back(path_it->initialPoint()); - - for (Geom::Path::const_iterator it = path_it->begin(), e = path_it->end_default(); it != e; ++it) { - pts.push_back((*it).finalPoint()); - } - //We use this fixed interpolator to simplfy the UI and for better results - Geom::Interpolate::Interpolator *interpolator = Geom::Interpolate::Interpolator::create(Geom::Interpolate::INTERP_CENTRIPETAL_CATMULLROM); - Geom::Path path = interpolator->interpolateToPath(pts); - - path_out.push_back(path); - } - pathv = path_out; - } - Geom::Interpolate::Interpolator *interpolator = Geom::Interpolate::Interpolator::create(static_cast(interpolator_type.get_value())); - if (Geom::Interpolate::CubicBezierJohan *johan = dynamic_cast(interpolator)) { - johan->setBeta(interpolator_beta); - } - if (Geom::Interpolate::CubicBezierSmooth *smooth = dynamic_cast(interpolator)) { - smooth->setBeta(interpolator_beta); - } - if (interpolate_original_prev != interpolate_original) { - adjustForNewPath(pathv); - interpolate_original_prev = interpolate_original; - } Geom::Piecewise > pwd2_in = pathv[0].toPwSb(); - if (!pwd2_in.size()) { - return path_in; - } Piecewise > der = derivative(pwd2_in); - if (!der.size()) { - return path_in; - } Piecewise > n = unitVector(der,0.0001); - if (!n.size()) { + if (!n.size() || !pwd2_in.size() || !n.size()) { return path_in; } + n = rot90(n); offset_points.set_pwd2(pwd2_in, n); @@ -654,116 +613,18 @@ LPEPowerStroke::doEffect_path (Geom::PathVector const & path_in) // instead of the heavily compressed coordinate system of (segment_no offset, Y) in which the knots are stored double pwd2_in_arclength = length(pwd2_in); double xcoord_scaling = pwd2_in_arclength / ts.back()[Geom::X]; - if (interpolate_original) { - size_t i = 0; - std::vector ts_aprox; - size_t steps = 0; - double distance = 0; - Geom::PathVector splits; - Geom::Coord start = 0; - for(std::vector::iterator point = ts.begin(); point != ts.end();) { - point++; - Geom::Coord end = (*point)[Geom::X]; - if (Geom::are_near(start, end,0.0001)) { - continue; - } - splits.push_back(path_in[0].portion(start, end)); - start = end; - if (end == pathv[0].size()) { - break; - } - } - size_t counter = 0; - for(Geom::PathVector::const_iterator path_it = splits.begin(); path_it != splits.end(); ++path_it) { - if (path_it->empty()) { - continue; - } - Geom::Piecewise > path_pwd = (*path_it).toPwSb(); - size_t size = (*path_it).size(); - double path_it_arclength = length(path_pwd); - Geom::Point start = ts[counter]; - counter++; - Geom::Point end = ts[counter]; - if (Geom::are_near(start[Geom::Y],end[Geom::Y],0.0001)) { - continue; - } - double gap = (start[Geom::Y] - end[Geom::Y])/size; - double width = 0; - width = start[Geom::Y]; - for (size_t j = 1; j < size; j++){ - Geom::Path current_curve = (*path_it).portion(j-1, j); - double path_it_arclength_sub = length(current_curve.toPwSb()); - double factor = path_it_arclength_sub * size/path_it_arclength; - width -= gap * factor; - ts.push_back(Geom::Point(std::floor(ts[counter-1][Geom::X]) + j, width)); - } - } - sort(ts.begin(), ts.end(), compare_offsets); + for (std::size_t i = 0, e = ts.size(); i < e; ++i) { + ts[i][Geom::X] *= xcoord_scaling; } // create stroke path where points (x,y) := (t, offset) - - Geom::Path fixed_path; - Geom::Path fixed_mirrorpath; - Geom::Path strokepath; - if (interpolate_original && 2==1) { - std::vector ts_normal; - std::vector ts_mirror; - - bool previous_isnode = false; - size_t counter = 0; - for(auto point:ts) { - Geom::Point normal_pos = pwd2_in.valueAt(point[Geom::X]) + (point[Geom::Y] * scale_width) * n.valueAt(point[Geom::X]); - Geom::Point mirror_pos = pwd2_in.valueAt(point[Geom::X]) + (point[Geom::Y] * -1 * scale_width) * n.valueAt(point[Geom::X]); - Geom::Point normal = Geom::Point(normal_pos[Geom::X] * xcoord_scaling, normal_pos[Geom::Y]); - Geom::Point mirror = Geom::Point(mirror_pos [Geom::X] * xcoord_scaling, mirror_pos [Geom::Y]); - //a bit smoothig tweak - if (counter > 2) { - Geom::Point granparent_normal = ts_normal[counter-2]; - Geom::Point parent_normal = ts_normal[counter-1]; - Geom::Point granparent_mirror = ts_mirror [counter-2]; - Geom::Point parent_mirror = ts_mirror [counter-1]; - bool isnode = ts[counter][Geom::X] == std::floor(ts[counter ][Geom::X]); - bool previous_isnode = ts[counter-1][Geom::X] == std::floor(ts[counter-1][Geom::X]); - bool ccw_toggle_normal = cross(parent_normal - granparent_normal, normal - granparent_normal) < 0; - bool ccw_toggle_mirror = cross(parent_mirror - granparent_mirror , mirror - granparent_mirror ) < 0; - Geom::Ray ray_normal_a(parent_normal, granparent_normal); - Geom::Ray ray_normal_b(parent_normal , normal); - Geom::Ray ray_mirror_a (parent_mirror, granparent_mirror); - Geom::Ray ray_mirror_b (parent_mirror , mirror); - double angle_normal = angle_between(ray_normal_a, ray_normal_b, ccw_toggle_normal); - double angle_mirror = angle_between(ray_mirror_a , ray_mirror_b , ccw_toggle_mirror); - if (point[Geom::X] > 2 && - previous_isnode && - !isnode && - !ccw_toggle_normal && - angle_normal < Geom::rad_from_deg(90)) - { - ts_normal.pop_back(); - } - if (point[Geom::X] > 2 && - previous_isnode && - !isnode && - ccw_toggle_mirror && - angle_mirror < Geom::rad_from_deg(90)) - { - ts_mirror.pop_back(); - } - } - ts_normal.push_back(normal); - ts_mirror.push_back(mirror); - counter++; - } - fixed_path = interpolator->interpolateToPath(ts_normal); - fixed_path *= Scale(1/xcoord_scaling, 1); - fixed_mirrorpath = interpolator->interpolateToPath(ts_mirror); - fixed_mirrorpath *= Scale(1/xcoord_scaling, 1); - fixed_mirrorpath = fixed_mirrorpath.reversed(); - } else { - for (std::size_t i = 0, e = ts.size(); i < e; ++i) { - ts[i][Geom::X] *= xcoord_scaling; - } - strokepath = interpolator->interpolateToPath(ts); + Geom::Interpolate::Interpolator *interpolator = Geom::Interpolate::Interpolator::create(static_cast(interpolator_type.get_value())); + if (Geom::Interpolate::CubicBezierJohan *johan = dynamic_cast(interpolator)) { + johan->setBeta(interpolator_beta); } + if (Geom::Interpolate::CubicBezierSmooth *smooth = dynamic_cast(interpolator)) { + smooth->setBeta(interpolator_beta); + } + Geom::Path strokepath = interpolator->interpolateToPath(ts); delete interpolator; // apply the inverse knot-xcoord scaling that was applied before the interpolation @@ -781,13 +642,13 @@ LPEPowerStroke::doEffect_path (Geom::PathVector const & path_in) y = portion(y, rtsmin.at(0), rtsmax.at(0)); } - if (!interpolate_original || 2>1) { - LineJoinType jointype = static_cast(linejoin_type.get_value()); - Piecewise > pwd2_out = compose(pwd2_in,x) + y*compose(n,x); - Piecewise > mirrorpath = reverse( compose(pwd2_in,x) - y*compose(n,x)); - fixed_path = path_from_piecewise_fix_cusps( pwd2_out, y, jointype, miter_limit, LPE_CONVERSION_TOLERANCE); - fixed_mirrorpath = path_from_piecewise_fix_cusps( mirrorpath, reverse(y), jointype, miter_limit, LPE_CONVERSION_TOLERANCE); - } + LineJoinType jointype = static_cast(linejoin_type.get_value()); + + Piecewise > pwd2_out = compose(pwd2_in,x) + y*compose(n,x); + Piecewise > mirrorpath = reverse( compose(pwd2_in,x) - y*compose(n,x)); + + Geom::Path fixed_path = path_from_piecewise_fix_cusps( pwd2_out, y, jointype, miter_limit, LPE_CONVERSION_TOLERANCE); + Geom::Path fixed_mirrorpath = path_from_piecewise_fix_cusps( mirrorpath, reverse(y), jointype, miter_limit, LPE_CONVERSION_TOLERANCE); if (pathv[0].closed()) { fixed_path.close(true); path_out.push_back(fixed_path); diff --git a/src/live_effects/lpe-powerstroke.h b/src/live_effects/lpe-powerstroke.h index 53aab1b05..19696ac57 100644 --- a/src/live_effects/lpe-powerstroke.h +++ b/src/live_effects/lpe-powerstroke.h @@ -38,7 +38,6 @@ public: private: BoolParam sort_points; - BoolParam interpolate_original; EnumParam interpolator_type; ScalarParam interpolator_beta; ScalarParam scale_width; @@ -46,7 +45,6 @@ private: EnumParam linejoin_type; ScalarParam miter_limit; EnumParam end_linecap_type; - bool interpolate_original_prev; LPEPowerStroke(const LPEPowerStroke&); LPEPowerStroke& operator=(const LPEPowerStroke&); }; -- cgit v1.2.3 From d9211f4fcd295d5a63bb713463487049311a24a2 Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Date: Tue, 26 Dec 2017 00:45:37 +0100 Subject: Fix start anchors --- src/live_effects/lpe-powerstroke.cpp | 27 +++++++++++++++++++++------ src/live_effects/lpeobject-reference.cpp | 6 ++++-- 2 files changed, 25 insertions(+), 8 deletions(-) (limited to 'src/live_effects') diff --git a/src/live_effects/lpe-powerstroke.cpp b/src/live_effects/lpe-powerstroke.cpp index e7ceaa397..995f0be35 100644 --- a/src/live_effects/lpe-powerstroke.cpp +++ b/src/live_effects/lpe-powerstroke.cpp @@ -325,7 +325,7 @@ static Geom::Path path_from_piecewise_fix_cusps( Geom::Piecewise > pwd2_in = pathv[0].toPwSb(); + if (pwd2_in.empty()) { + return path_in; + } Piecewise > der = derivative(pwd2_in); - Piecewise > n = unitVector(der,0.0001); - if (!n.size() || !pwd2_in.size() || !n.size()) { + if (der.empty()) { + return path_in; + } + Piecewise > n = unitVector(der,0.00001); + if (n.empty()) { return path_in; } @@ -598,8 +603,16 @@ LPEPowerStroke::doEffect_path (Geom::PathVector const & path_in) // add extra points for interpolation between first and last point Point first_point = ts.front(); Point last_point = ts.back(); + //TODO: this is wrong we need to give a calulated Y value ts.insert(ts.begin(), last_point - Point(pwd2_in.domain().extent() ,0)); - ts.push_back( first_point + Point(pwd2_in.domain().extent() ,0) ); +// double startpercentwidth = ts.front()[Geom::X]/pwd2_in.domain().max(); +// double endpercentwidth = (pwd2_in.domain().max() - ts.back()[Geom::X])/pwd2_in.domain().max(); +// double totalwidth = endpercentwidth + startpercentwidth ; +// double factor = endpercentwidth/totalwidth; +// std::cout << factor << "factor" << std::endl; +// double gap = ts.front()[Geom::Y] - ts.back()[Geom::Y]; +// ts.insert(ts.begin(), Point( pwd2_in.domain().min(), ts.back()[Geom::Y] - (gap / factor) ) ); +// ts.push_back( Point( pwd2_in.domain().max(), ts.back()[Geom::Y] - (gap / factor) ) ); } else { // add width data for first and last point on the path // depending on cap type, these first and last points have width zero or take the width from the closest width point. @@ -643,7 +656,9 @@ LPEPowerStroke::doEffect_path (Geom::PathVector const & path_in) } LineJoinType jointype = static_cast(linejoin_type.get_value()); - + if (x.empty() || y.empty()) { + return path_in; + } Piecewise > pwd2_out = compose(pwd2_in,x) + y*compose(n,x); Piecewise > mirrorpath = reverse( compose(pwd2_in,x) - y*compose(n,x)); diff --git a/src/live_effects/lpeobject-reference.cpp b/src/live_effects/lpeobject-reference.cpp index 83cd6623c..89df843e8 100644 --- a/src/live_effects/lpeobject-reference.cpp +++ b/src/live_effects/lpeobject-reference.cpp @@ -76,8 +76,10 @@ LPEObjectReference::link(const char *to) void LPEObjectReference::unlink(void) { - g_free(lpeobject_href); - lpeobject_href = NULL; + if (lpeobject_href) { + g_free(lpeobject_href); + lpeobject_href = NULL; + } detach(); } -- cgit v1.2.3 From d25de3679d94cc03fdba8aba4de20fab723b4b27 Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Date: Tue, 26 Dec 2017 17:14:27 +0100 Subject: Fix power stroke closed path and minor tweacks for pencil powerstroke --- src/live_effects/lpe-powerstroke.cpp | 48 ++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 21 deletions(-) (limited to 'src/live_effects') diff --git a/src/live_effects/lpe-powerstroke.cpp b/src/live_effects/lpe-powerstroke.cpp index 995f0be35..4e937c1e4 100644 --- a/src/live_effects/lpe-powerstroke.cpp +++ b/src/live_effects/lpe-powerstroke.cpp @@ -599,20 +599,33 @@ LPEPowerStroke::doEffect_path (Geom::PathVector const & path_in) if (sort_points) { sort(ts.begin(), ts.end(), compare_offsets); } + // create stroke path where points (x,y) := (t, offset) + Geom::Interpolate::Interpolator *interpolator = Geom::Interpolate::Interpolator::create(static_cast(interpolator_type.get_value())); + if (Geom::Interpolate::CubicBezierJohan *johan = dynamic_cast(interpolator)) { + johan->setBeta(interpolator_beta); + } + if (Geom::Interpolate::CubicBezierSmooth *smooth = dynamic_cast(interpolator)) { + smooth->setBeta(interpolator_beta); + } if (pathv[0].closed()) { - // add extra points for interpolation between first and last point - Point first_point = ts.front(); - Point last_point = ts.back(); - //TODO: this is wrong we need to give a calulated Y value - ts.insert(ts.begin(), last_point - Point(pwd2_in.domain().extent() ,0)); -// double startpercentwidth = ts.front()[Geom::X]/pwd2_in.domain().max(); -// double endpercentwidth = (pwd2_in.domain().max() - ts.back()[Geom::X])/pwd2_in.domain().max(); -// double totalwidth = endpercentwidth + startpercentwidth ; -// double factor = endpercentwidth/totalwidth; -// std::cout << factor << "factor" << std::endl; -// double gap = ts.front()[Geom::Y] - ts.back()[Geom::Y]; -// ts.insert(ts.begin(), Point( pwd2_in.domain().min(), ts.back()[Geom::Y] - (gap / factor) ) ); -// ts.push_back( Point( pwd2_in.domain().max(), ts.back()[Geom::Y] - (gap / factor) ) ); + std::vector ts_close; + //we have only one knot or overwrite before + Geom::Point start = Geom::Point( pwd2_in.domain().min(), ts.front()[Geom::Y]); + Geom::Point end = Geom::Point( pwd2_in.domain().max(), ts.front()[Geom::Y]); + if (ts.size() > 1) { + ts_close.push_back(ts[ts.size()-2]); + ts_close.push_back(ts.back()); + ts_close.push_back(ts.front()); + ts_close.push_back(ts[1]); + Geom::Path closepath = interpolator->interpolateToPath(ts_close); + start = closepath.pointAt(Geom::nearest_time(Geom::Point( pwd2_in.domain().min(),0), closepath)); + start[Geom::X] = pwd2_in.domain().min(); + end = start; + end[Geom::X] = pwd2_in.domain().max(); + } + ts.insert(ts.begin(), start ); + ts.push_back( end ); + ts_close.clear(); } else { // add width data for first and last point on the path // depending on cap type, these first and last points have width zero or take the width from the closest width point. @@ -629,14 +642,7 @@ LPEPowerStroke::doEffect_path (Geom::PathVector const & path_in) for (std::size_t i = 0, e = ts.size(); i < e; ++i) { ts[i][Geom::X] *= xcoord_scaling; } - // create stroke path where points (x,y) := (t, offset) - Geom::Interpolate::Interpolator *interpolator = Geom::Interpolate::Interpolator::create(static_cast(interpolator_type.get_value())); - if (Geom::Interpolate::CubicBezierJohan *johan = dynamic_cast(interpolator)) { - johan->setBeta(interpolator_beta); - } - if (Geom::Interpolate::CubicBezierSmooth *smooth = dynamic_cast(interpolator)) { - smooth->setBeta(interpolator_beta); - } + Geom::Path strokepath = interpolator->interpolateToPath(ts); delete interpolator; -- cgit v1.2.3 From 421d3605d3c6dd8a54a36236cbeb478dff06f194 Mon Sep 17 00:00:00 2001 From: Jabiertxo Arraiza Cenoz Date: Wed, 27 Dec 2017 19:38:11 +0100 Subject: Allow erase knots in powerstroke --- .../parameter/powerstrokepointarray.cpp | 29 +++++++++++----------- 1 file changed, 14 insertions(+), 15 deletions(-) (limited to 'src/live_effects') diff --git a/src/live_effects/parameter/powerstrokepointarray.cpp b/src/live_effects/parameter/powerstrokepointarray.cpp index 289498498..64c772602 100644 --- a/src/live_effects/parameter/powerstrokepointarray.cpp +++ b/src/live_effects/parameter/powerstrokepointarray.cpp @@ -230,22 +230,21 @@ PowerStrokePointArrayParamKnotHolderEntity::knot_click(guint state) if (state & GDK_MOD1_MASK) { // delete the clicked knot std::vector & vec = _pparam->_vector; - vec.erase(vec.begin() + _index); - _pparam->param_set_and_write_new_value(vec); - - // remove knot from knotholder - parent_holder->entity.remove(this); - // shift knots down one index - for(std::list::iterator ent = parent_holder->entity.begin(); ent != parent_holder->entity.end(); ++ent) { - PowerStrokePointArrayParamKnotHolderEntity *pspa_ent = dynamic_cast(*ent); - if ( pspa_ent && pspa_ent->_pparam == this->_pparam ) { // check if the knotentity belongs to this powerstrokepointarray parameter - if (pspa_ent->_index > this->_index) { - --pspa_ent->_index; + if (vec.size() > 1) { //Force dont remove last knot + vec.erase(vec.begin() + _index); + _pparam->param_set_and_write_new_value(vec); + // shift knots down one index + for(std::list::iterator ent = parent_holder->entity.begin(); ent != parent_holder->entity.end(); ++ent) { + PowerStrokePointArrayParamKnotHolderEntity *pspa_ent = dynamic_cast(*ent); + if ( pspa_ent && pspa_ent->_pparam == this->_pparam ) { // check if the knotentity belongs to this powerstrokepointarray parameter + if (pspa_ent->_index > this->_index) { + --pspa_ent->_index; + } } - } - }; - // delete self and return - delete this; + }; + // temporary hide, when knotholder were recreated it finaly drop + this->knot->hide(); + } return; } else { // add a knot to XML -- cgit v1.2.3