diff options
| author | Jabier Arraiza <jabier.arraiza@marker.es> | 2017-12-18 00:11:36 +0000 |
|---|---|---|
| committer | Jabier Arraiza <jabier.arraiza@marker.es> | 2017-12-18 00:11:36 +0000 |
| commit | 3d059a10fd17411f73e88ccde2cd853642ee7dc3 (patch) | |
| tree | b7cb670dea4d6f20b86b583329a457bf1772f2e2 /src/live_effects | |
| parent | Merge branch 'master' into powerpencilII (diff) | |
| download | inkscape-3d059a10fd17411f73e88ccde2cd853642ee7dc3.tar.gz inkscape-3d059a10fd17411f73e88ccde2cd853642ee7dc3.zip | |
Working on powerstroke fixes to pentool
Diffstat (limited to 'src/live_effects')
| -rw-r--r-- | src/live_effects/lpe-powerstroke.cpp | 185 | ||||
| -rw-r--r-- | src/live_effects/lpe-powerstroke.h | 2 |
2 files changed, 23 insertions, 164 deletions
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<SBasis> 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<D2<SBasis> > unitv = unitVector(dM,tol); + if (unitv.empty()) { // admit defeat + return Geom::Circle(Geom::Point(0., 0.), 0.); + } Piecewise<SBasis> dMlength = dot(Piecewise<D2<SBasis> >(dM),unitv); Piecewise<SBasis> 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<Geom::Point> 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<Geom::Interpolate::InterpolatorType>(interpolator_type.get_value())); - if (Geom::Interpolate::CubicBezierJohan *johan = dynamic_cast<Geom::Interpolate::CubicBezierJohan*>(interpolator)) { - johan->setBeta(interpolator_beta); - } - if (Geom::Interpolate::CubicBezierSmooth *smooth = dynamic_cast<Geom::Interpolate::CubicBezierSmooth*>(interpolator)) { - smooth->setBeta(interpolator_beta); - } - if (interpolate_original_prev != interpolate_original) { - adjustForNewPath(pathv); - interpolate_original_prev = interpolate_original; - } Geom::Piecewise<Geom::D2<Geom::SBasis> > pwd2_in = pathv[0].toPwSb(); - if (!pwd2_in.size()) { - return path_in; - } Piecewise<D2<SBasis> > der = derivative(pwd2_in); - if (!der.size()) { - return path_in; - } Piecewise<D2<SBasis> > 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<Geom::Point> ts_aprox; - size_t steps = 0; - double distance = 0; - Geom::PathVector splits; - Geom::Coord start = 0; - for(std::vector<Geom::Point>::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<Geom::D2<Geom::SBasis> > 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<Geom::Point> ts_normal; - std::vector<Geom::Point> 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<Geom::Interpolate::InterpolatorType>(interpolator_type.get_value())); + if (Geom::Interpolate::CubicBezierJohan *johan = dynamic_cast<Geom::Interpolate::CubicBezierJohan*>(interpolator)) { + johan->setBeta(interpolator_beta); } + if (Geom::Interpolate::CubicBezierSmooth *smooth = dynamic_cast<Geom::Interpolate::CubicBezierSmooth*>(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<LineJoinType>(linejoin_type.get_value()); - Piecewise<D2<SBasis> > pwd2_out = compose(pwd2_in,x) + y*compose(n,x); - Piecewise<D2<SBasis> > 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<LineJoinType>(linejoin_type.get_value()); + + Piecewise<D2<SBasis> > pwd2_out = compose(pwd2_in,x) + y*compose(n,x); + Piecewise<D2<SBasis> > 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<unsigned> interpolator_type; ScalarParam interpolator_beta; ScalarParam scale_width; @@ -46,7 +45,6 @@ private: EnumParam<unsigned> linejoin_type; ScalarParam miter_limit; EnumParam<unsigned> end_linecap_type; - bool interpolate_original_prev; LPEPowerStroke(const LPEPowerStroke&); LPEPowerStroke& operator=(const LPEPowerStroke&); }; |
