diff options
| author | Liam P. White <inkscapebronyat-signgmaildotcom> | 2014-04-02 21:18:40 +0000 |
|---|---|---|
| committer | Liam P. White <inkscapebronyat-signgmaildotcom> | 2014-04-02 21:18:40 +0000 |
| commit | d20b73d611b6de99e0e0697ee47a760de437ee97 (patch) | |
| tree | 3069592be43d6d60466d6ba0bb418a7f5ed11bd1 /src | |
| parent | Fix some stuff (diff) | |
| download | inkscape-d20b73d611b6de99e0e0697ee47a760de437ee97.tar.gz inkscape-d20b73d611b6de99e0e0697ee47a760de437ee97.zip | |
Clean up code
(bzr r13090.1.42)
Diffstat (limited to 'src')
| -rw-r--r--[-rwxr-xr-x] | src/live_effects/lpe-taperstroke.cpp | 905 | ||||
| -rw-r--r-- | src/live_effects/lpe-taperstroke.h | 48 | ||||
| -rw-r--r--[-rwxr-xr-x] | src/live_effects/pathoutlineprovider.cpp | 521 | ||||
| -rw-r--r-- | src/live_effects/pathoutlineprovider.h | 16 |
4 files changed, 765 insertions, 725 deletions
diff --git a/src/live_effects/lpe-taperstroke.cpp b/src/live_effects/lpe-taperstroke.cpp index b4e43209d..97ae02e3b 100755..100644 --- a/src/live_effects/lpe-taperstroke.cpp +++ b/src/live_effects/lpe-taperstroke.cpp @@ -38,26 +38,27 @@ namespace Inkscape { namespace LivePathEffect { namespace TpS { - class KnotHolderEntityAttachBegin : public LPEKnotHolderEntity { - public: - KnotHolderEntityAttachBegin(LPETaperStroke * effect) : LPEKnotHolderEntity(effect) {} - virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); - virtual Geom::Point knot_get() const; - }; - class KnotHolderEntityAttachEnd : public LPEKnotHolderEntity { - public: - KnotHolderEntityAttachEnd(LPETaperStroke * effect) : LPEKnotHolderEntity(effect) {} - virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); - virtual Geom::Point knot_get() const; - }; + class KnotHolderEntityAttachBegin : public LPEKnotHolderEntity { + public: + KnotHolderEntityAttachBegin(LPETaperStroke * effect) : LPEKnotHolderEntity(effect) {} + virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); + virtual Geom::Point knot_get() const; + }; + + class KnotHolderEntityAttachEnd : public LPEKnotHolderEntity { + public: + KnotHolderEntityAttachEnd(LPETaperStroke * effect) : LPEKnotHolderEntity(effect) {} + virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); + virtual Geom::Point knot_get() const; + }; } // TpS static const Util::EnumData<unsigned> JoinType[] = { - {LINEJOIN_STRAIGHT, N_("Beveled"), "bevel"}, - {LINEJOIN_ROUND, N_("Rounded"), "round"}, - {LINEJOIN_REFLECTED, N_("Reflected"), "reflected"}, - {LINEJOIN_POINTY, N_("Miter"), "miter"}, - {LINEJOIN_EXTRAPOLATED, N_("Extrapolated"), "extrapolated"} + {LINEJOIN_STRAIGHT, N_("Beveled"), "bevel"}, + {LINEJOIN_ROUND, N_("Rounded"), "round"}, + {LINEJOIN_REFLECTED, N_("Reflected"), "reflected"}, + {LINEJOIN_POINTY, N_("Miter"), "miter"}, + {LINEJOIN_EXTRAPOLATED, N_("Extrapolated"), "extrapolated"} }; static const Util::EnumDataConverter<unsigned> JoinTypeConverter(JoinType, sizeof (JoinType)/sizeof(*JoinType)); @@ -65,31 +66,30 @@ static const Util::EnumDataConverter<unsigned> JoinTypeConverter(JoinType, sizeo LPETaperStroke::LPETaperStroke(LivePathEffectObject *lpeobject) : Effect(lpeobject), line_width(_("Stroke width"), _("The (non-tapered) width of the path"), "stroke_width", &wr, this, 3), - attach_start(_("Start offset"), _("Taper distance from path start"), "attach_start", &wr, this, 0.2), - attach_end(_("End offset"), _("The ending position of the taper"), "end_offset", &wr, this, 0.2), - smoothing(_("Taper smoothing"), _("Amount of smoothing to apply to the tapers"), "smoothing", &wr, this, 0.5), - join_type(_("Join type"), _("Join type for non-smooth nodes"), "jointype", JoinTypeConverter, &wr, this, LINEJOIN_EXTRAPOLATED), - miter_limit(_("Miter limit"), _("Limit for miter joins"), "miter_limit", &wr, this, 30.) + attach_start(_("Start offset"), _("Taper distance from path start"), "attach_start", &wr, this, 0.2), + attach_end(_("End offset"), _("The ending position of the taper"), "end_offset", &wr, this, 0.2), + smoothing(_("Taper smoothing"), _("Amount of smoothing to apply to the tapers"), "smoothing", &wr, this, 0.5), + join_type(_("Join type"), _("Join type for non-smooth nodes"), "jointype", JoinTypeConverter, &wr, this, LINEJOIN_EXTRAPOLATED), + miter_limit(_("Miter limit"), _("Limit for miter joins"), "miter_limit", &wr, this, 30.) { - /* uncomment the following line to have the original path displayed while the item is selected */ show_orig_path = true; - _provides_knotholder_entities = true; - - attach_start.param_set_digits(3); - attach_end.param_set_digits(3); - - - registerParameter( dynamic_cast<Parameter *>(&line_width) ); - registerParameter( dynamic_cast<Parameter *>(&attach_start) ); - registerParameter( dynamic_cast<Parameter *>(&attach_end) ); - registerParameter( dynamic_cast<Parameter *>(&smoothing) ); - registerParameter( dynamic_cast<Parameter *>(&join_type) ); - registerParameter( dynamic_cast<Parameter *>(&miter_limit) ); + _provides_knotholder_entities = true; + + attach_start.param_set_digits(3); + attach_end.param_set_digits(3); + + + registerParameter( dynamic_cast<Parameter *>(&line_width) ); + registerParameter( dynamic_cast<Parameter *>(&attach_start) ); + registerParameter( dynamic_cast<Parameter *>(&attach_end) ); + registerParameter( dynamic_cast<Parameter *>(&smoothing) ); + registerParameter( dynamic_cast<Parameter *>(&join_type) ); + registerParameter( dynamic_cast<Parameter *>(&miter_limit) ); } LPETaperStroke::~LPETaperStroke() { - + } //from LPEPowerStroke -- sets fill if stroke color because we will @@ -97,10 +97,10 @@ LPETaperStroke::~LPETaperStroke() void LPETaperStroke::doOnApply(SPLPEItem const* lpeitem) { - if (SP_IS_SHAPE(lpeitem)) { + if (SP_IS_SHAPE(lpeitem)) { SPLPEItem* item = const_cast<SPLPEItem*>(lpeitem); double width = (lpeitem && lpeitem->style) ? lpeitem->style->stroke_width.computed : 1.; - + SPCSSAttr *css = sp_repr_css_attr_new (); if (lpeitem->style->stroke.isSet()) { if (lpeitem->style->stroke.isPaintserver()) { @@ -122,13 +122,13 @@ void LPETaperStroke::doOnApply(SPLPEItem const* lpeitem) } else { sp_repr_css_unset_property (css, "fill"); } - + sp_repr_css_set_property(css, "stroke", "none"); - + sp_desktop_apply_css_recursive(item, css, true); sp_repr_css_attr_unref (css); - line_width.param_set_value(width); + line_width.param_set_value(width); } else { g_warning("LPE Join Type can only be applied to paths (not groups)."); } @@ -138,8 +138,10 @@ void LPETaperStroke::doOnApply(SPLPEItem const* lpeitem) void LPETaperStroke::doOnRemove(SPLPEItem const* lpeitem) { - - if (SP_IS_SHAPE(lpeitem)) { + + if (SP_IS_SHAPE(lpeitem)) { + //TODO: make it getobjbyrepr instead of const_cast because this can cause + //undefined behavior SPLPEItem *item = const_cast<SPLPEItem*>(lpeitem); SPCSSAttr *css = sp_repr_css_attr_new (); @@ -164,7 +166,7 @@ void LPETaperStroke::doOnRemove(SPLPEItem const* lpeitem) sp_repr_css_unset_property (css, "stroke"); } - Inkscape::CSSOStringStream os; + Inkscape::CSSOStringStream os; os << fabs(line_width); sp_repr_css_set_property (css, "stroke-width", os.str().c_str()); @@ -173,335 +175,347 @@ void LPETaperStroke::doOnRemove(SPLPEItem const* lpeitem) sp_desktop_apply_css_recursive(item, css, true); sp_repr_css_attr_unref (css); item->updateRepr(); - } + } } //actual effect impl here Geom::Path return_at_first_cusp (Geom::Path const & path_in, double smooth_tolerance = 0.05) { - Geom::Path path_out = Geom::Path(); - - for (unsigned i = 0; i < path_in.size(); i++) - { - path_out.append(path_in[i]); - if (path_in.size() == 1) - break; - - //determine order of curve - int order = Outline::bezierOrder(&path_in[i]); - - Geom::Point start_point; - Geom::Point cross_point = path_in[i].finalPoint(); - Geom::Point end_point; - - g_assert(path_in[i].finalPoint() == path_in[i+1].initialPoint()); - - //can you tell that the following expressions have been shaped by - //repeated compiler errors? ;) - switch (order) - { - case 3: - start_point = (static_cast<const Geom::CubicBezier*>(&path_in[i]))->operator[] (2); - //major league b***f***ing - if (are_near(start_point, cross_point, 0.0000001)) { - start_point = (static_cast<const Geom::CubicBezier*>(&path_in[i]))->operator[] (1); - } - break; - case 2: - //this never happens - start_point = (static_cast<const Geom::QuadraticBezier*>(&path_in[i]))->operator[] (1); - break; - case 1: - default: - start_point = path_in[i].initialPoint(); - } - - order = Outline::bezierOrder(&path_in[i+1]); - - switch (order) - { - case 3: - end_point = (static_cast<const Geom::CubicBezier*>(&path_in[i+1]))->operator[] (1); - if (are_near(end_point, cross_point, 0.0000001)) { - end_point = (static_cast<const Geom::CubicBezier*>(&path_in[i+1]))->operator[] (2); - } - break; - case 2: - end_point = (static_cast<const Geom::QuadraticBezier*>(&path_in[i+1]))->operator[] (1); - break; - case 1: - default: - end_point = path_in[i+1].finalPoint(); - } - - g_assert(!are_near(start_point, cross_point, 0.0000001)); //take that motherf*ckers - g_assert(!are_near(cross_point, end_point, 0.0000001)); - g_assert(!are_near(start_point, end_point, 0.0000001)); - - if (!are_collinear(start_point, cross_point, end_point, smooth_tolerance)) - break; - } - return path_out; + Geom::Path path_out = Geom::Path(); + + for (unsigned i = 0; i < path_in.size(); i++) { + path_out.append(path_in[i]); + if (path_in.size() == 1) + break; + + //determine order of curve + int order = Outline::bezierOrder(&path_in[i]); + + Geom::Point start_point; + Geom::Point cross_point = path_in[i].finalPoint(); + Geom::Point end_point; + + g_assert(path_in[i].finalPoint() == path_in[i+1].initialPoint()); + + //can you tell that the following expressions have been shaped by + //repeated compiler errors? ;) + switch (order) { + case 3: + start_point = (static_cast<const Geom::CubicBezier*>(&path_in[i]))->operator[] (2); + //major league b***f***ing + if (are_near(start_point, cross_point, 0.0000001)) { + start_point = (static_cast<const Geom::CubicBezier*>(&path_in[i]))->operator[] (1); + } + break; + case 2: + //this never happens + start_point = (static_cast<const Geom::QuadraticBezier*>(&path_in[i]))->operator[] (1); + break; + case 1: + default: + start_point = path_in[i].initialPoint(); + } + + order = Outline::bezierOrder(&path_in[i+1]); + + switch (order) { + case 3: + end_point = (static_cast<const Geom::CubicBezier*>(&path_in[i+1]))->operator[] (1); + if (are_near(end_point, cross_point, 0.0000001)) { + end_point = (static_cast<const Geom::CubicBezier*>(&path_in[i+1]))->operator[] (2); + } + break; + case 2: + end_point = (static_cast<const Geom::QuadraticBezier*>(&path_in[i+1]))->operator[] (1); + break; + case 1: + default: + end_point = path_in[i+1].finalPoint(); + } + + //clearly it's collinear if two occupy the same point + g_assert(!are_near(start_point, cross_point, 0.0000001)); + g_assert(!are_near(cross_point, end_point, 0.0000001)); + g_assert(!are_near(start_point, end_point, 0.0000001)); + + if (!are_collinear(start_point, cross_point, end_point, smooth_tolerance)) + break; + } + return path_out; } Geom::Piecewise<Geom::D2<Geom::SBasis> > stretch_along(Geom::Piecewise<Geom::D2<Geom::SBasis> > pwd2_in, Geom::Path pattern, double width); +//references to pointers, because magic +void subdivideCurve(Geom::Curve * curve_in, Geom::Coord t, Geom::Curve *& val_first, Geom::Curve *& val_second); Geom::PathVector LPETaperStroke::doEffect_path(Geom::PathVector const& path_in) { - Geom::Path first_cusp = return_at_first_cusp(path_in[0]); - Geom::Path last_cusp = return_at_first_cusp(path_in[0].reverse()); - - bool zeroStart = false; - bool zeroEnd = false; - //there is a pretty good chance that people will try to drag the knots - //on top of each other, so block it - - unsigned size = path_in[0].size(); - if (size == first_cusp.size()) { - //check to see if the knots were dragged over each other - //if so, reset the end offset - if ( attach_start >= (size - attach_end) ) { - attach_end.param_set_value( size - attach_start ); - } - } - - //don't ever let it be zero - if (attach_start <= 0.00000001) { - attach_start.param_set_value( 0.00000001 ); - zeroStart = true; - } - if (attach_end <= 0.00000001) { - attach_end.param_set_value( 0.00000001 ); - zeroEnd = true; - } - - //don't let it be integer - if (double(unsigned(attach_start)) == attach_start) { - attach_start.param_set_value(attach_start - 0.00001); - } - if (double(unsigned(attach_end)) == attach_end) { - attach_end.param_set_value(attach_end - 0.00001); - } - - unsigned allowed_start = first_cusp.size(); - unsigned allowed_end = last_cusp.size(); - - //don't let the knots be farther than they are allowed to be - if ((unsigned)attach_start >= allowed_start) { - attach_start.param_set_value((double)allowed_start - 0.00000001); - } - if ((unsigned)attach_end >= allowed_end) { - attach_end.param_set_value((double)allowed_end - 0.00000001); - } - - //remember, Path::operator () means get point at time t - start_attach_point = first_cusp(attach_start); - end_attach_point = last_cusp(attach_end); - Geom::PathVector pathv_out; - - //the following function just splits it up into three pieces. - pathv_out = doEffect_simplePath(path_in); - - //now for the actual tapering. We use a Pattern Along Path method to get this done. - - Geom::PathVector real_pathv; - Geom::Path real_path; - Geom::PathVector pat_vec; - Geom::Piecewise<Geom::D2<Geom::SBasis> > pwd2; - Geom::Path throwaway_path; - - if (!zeroStart) { - //Construct the pattern (pat_str stands for pattern string) (yes, this is easier, trust me) - std::stringstream pat_str; - pat_str << "M 1,0 C " << 1 - (double)smoothing << ",0 0,0.5 0,0.5 0,0.5 " << 1 - (double)smoothing << ",1 1,1"; - - pat_vec = sp_svg_read_pathv(pat_str.str().c_str()); - pwd2.concat(stretch_along(pathv_out[0].toPwSb(), pat_vec[0], -fabs(line_width))); - throwaway_path = Geom::path_from_piecewise(pwd2, 0.001)[0]; - - real_path.append(throwaway_path); - } - //append the outside outline of the path (with direction) - throwaway_path = Outline::PathOutsideOutline(pathv_out[1], - -fabs(line_width), static_cast<LineJoinType>(join_type.get_value()), miter_limit); - - if (!zeroStart) { - throwaway_path.setInitial(real_path.finalPoint()); - real_path.append(throwaway_path); - } else { - real_path.append(throwaway_path, Geom::Path::STITCH_DISCONTINUOUS); - } - - if (!zeroEnd) { - //append the ending taper - std::stringstream pat_str_1; - pat_str_1 << "M 0,0 0,1 C " << (double)smoothing << ",1 1,0.5 1,0.5 1,0.5 " << double(smoothing) << ",0 0,0"; - pat_vec = sp_svg_read_pathv(pat_str_1.str().c_str()); - - pwd2 = Geom::Piecewise<Geom::D2<Geom::SBasis> > (); - pwd2.concat(stretch_along(pathv_out[2].toPwSb(), pat_vec[0], -fabs(line_width))); - - throwaway_path = Geom::path_from_piecewise(pwd2, 0.001)[0]; - throwaway_path.setInitial(real_path.finalPoint()); - real_path.append(throwaway_path); - } - //append the inside outline of the path (against direction) - throwaway_path = Outline::PathOutsideOutline(pathv_out[1].reverse(), - -fabs(line_width), static_cast<LineJoinType>(join_type.get_value()), miter_limit); - - if (!zeroEnd) { - //throwaway_path.setInitial(real_path.finalPoint()); - real_path.append(throwaway_path, Geom::Path::STITCH_DISCONTINUOUS); - } else { - real_path.append(throwaway_path, Geom::Path::STITCH_DISCONTINUOUS); - } - real_path.close(); - - real_pathv.push_back(real_path); - - return real_pathv; + Geom::Path first_cusp = return_at_first_cusp(path_in[0]); + Geom::Path last_cusp = return_at_first_cusp(path_in[0].reverse()); + + bool zeroStart = false; + bool zeroEnd = false; + //there is a pretty good chance that people will try to drag the knots + //on top of each other, so block it + + unsigned size = path_in[0].size(); + if (size == first_cusp.size()) { + //check to see if the knots were dragged over each other + //if so, reset the end offset + if ( attach_start >= (size - attach_end) ) { + attach_end.param_set_value( size - attach_start ); + } + } + + //don't ever let it be zero + if (attach_start <= 0.00000001) { + attach_start.param_set_value( 0.00000001 ); + zeroStart = true; + } + if (attach_end <= 0.00000001) { + attach_end.param_set_value( 0.00000001 ); + zeroEnd = true; + } + + //don't let it be integer + if (double(unsigned(attach_start)) == attach_start) { + attach_start.param_set_value(attach_start - 0.00001); + } + if (double(unsigned(attach_end)) == attach_end) { + attach_end.param_set_value(attach_end - 0.00001); + } + + unsigned allowed_start = first_cusp.size(); + unsigned allowed_end = last_cusp.size(); + + //don't let the knots be farther than they are allowed to be + if ((unsigned)attach_start >= allowed_start) { + attach_start.param_set_value((double)allowed_start - 0.00000001); + } + if ((unsigned)attach_end >= allowed_end) { + attach_end.param_set_value((double)allowed_end - 0.00000001); + } + + //remember, Path::operator () means get point at time t + start_attach_point = first_cusp(attach_start); + end_attach_point = last_cusp(attach_end); + Geom::PathVector pathv_out; + + //the following function just splits it up into three pieces. + pathv_out = doEffect_simplePath(path_in); + + //now for the actual tapering. We use a Pattern Along Path method to get this done. + + Geom::PathVector real_pathv; + Geom::Path real_path; + Geom::PathVector pat_vec; + Geom::Piecewise<Geom::D2<Geom::SBasis> > pwd2; + Geom::Path throwaway_path; + + if (!zeroStart) { + //Construct the pattern (pat_str stands for pattern string) (yes, this is easier, trust me) + std::stringstream pat_str; + pat_str << "M 1,0 C " << 1 - (double)smoothing << ",0 0,0.5 0,0.5 0,0.5 " << 1 - (double)smoothing << ",1 1,1"; + + pat_vec = sp_svg_read_pathv(pat_str.str().c_str()); + pwd2.concat(stretch_along(pathv_out[0].toPwSb(), pat_vec[0], -fabs(line_width))); + throwaway_path = Geom::path_from_piecewise(pwd2, 0.001)[0]; + + real_path.append(throwaway_path); + } + //append the outside outline of the path (with direction) + throwaway_path = Outline::PathOutsideOutline(pathv_out[1], + -fabs(line_width), static_cast<LineJoinType>(join_type.get_value()), miter_limit); + + if (!zeroStart) { + throwaway_path.setInitial(real_path.finalPoint()); + real_path.append(throwaway_path); + } else { + real_path.append(throwaway_path, Geom::Path::STITCH_DISCONTINUOUS); + } + + if (!zeroEnd) { + //append the ending taper + std::stringstream pat_str_1; + pat_str_1 << "M 0,0 0,1 C " << (double)smoothing << ",1 1,0.5 1,0.5 1,0.5 " << double(smoothing) << ",0 0,0"; + pat_vec = sp_svg_read_pathv(pat_str_1.str().c_str()); + + pwd2 = Geom::Piecewise<Geom::D2<Geom::SBasis> > (); + pwd2.concat(stretch_along(pathv_out[2].toPwSb(), pat_vec[0], -fabs(line_width))); + + throwaway_path = Geom::path_from_piecewise(pwd2, 0.001)[0]; + throwaway_path.setInitial(real_path.finalPoint()); + real_path.append(throwaway_path); + } + //append the inside outline of the path (against direction) + throwaway_path = Outline::PathOutsideOutline(pathv_out[1].reverse(), + -fabs(line_width), static_cast<LineJoinType>(join_type.get_value()), miter_limit); + + if (!zeroEnd) { + //throwaway_path.setInitial(real_path.finalPoint()); + real_path.append(throwaway_path, Geom::Path::STITCH_DISCONTINUOUS); + } else { + real_path.append(throwaway_path, Geom::Path::STITCH_DISCONTINUOUS); + } + + //hmm + real_path.setFinal(real_path.initialPoint()); + + real_path.close(); + + real_pathv.push_back(real_path); + + return real_pathv; } //in all cases, this should return a PathVector with three elements. Geom::PathVector LPETaperStroke::doEffect_simplePath(Geom::PathVector const & path_in) { - unsigned size = path_in[0].size(); - - //do subdivision and get out - unsigned loc = (unsigned)attach_start; - Geom::Curve * curve_start = path_in[0] [loc].duplicate(); - - std::vector<Geom::Path> pathv_out; - Geom::Path path_out = Geom::Path(); - - Geom::Path trimmed_start = Geom::Path(); - Geom::Path trimmed_end = Geom::Path(); - - for (unsigned i = 0; i < loc; i++) { - trimmed_start.append(path_in[0] [i]); - } - - - //this is pretty annoying - //previously I wrote a function for this but it wasted a lot of time - //so I optimized it back into here. - unsigned order = Outline::bezierOrder(curve_start); - switch (order) { - case 3: { - Geom::CubicBezier *cb = static_cast<Geom::CubicBezier * >(curve_start); - std::pair<Geom::CubicBezier, Geom::CubicBezier> cb_pair = cb->subdivide((attach_start - loc)); - trimmed_start.append(cb_pair.first); curve_start = cb_pair.second.duplicate(); //goes out of scope - break; - } - case 2: { - Geom::QuadraticBezier *qb = static_cast<Geom::QuadraticBezier * >(curve_start); - std::pair<Geom::QuadraticBezier, Geom::QuadraticBezier> qb_pair = qb->subdivide((attach_start - loc)); - trimmed_start.append(qb_pair.first); curve_start = qb_pair.second.duplicate(); - break; - } - case 1: { - Geom::BezierCurveN<1> *lb = static_cast<Geom::BezierCurveN<1> * >(curve_start); - std::pair<Geom::BezierCurveN<1>, Geom::BezierCurveN<1> > lb_pair = lb->subdivide((attach_start - loc)); - trimmed_start.append(lb_pair.first); curve_start = lb_pair.second.duplicate(); - break; - } - } - - //special case: path is one segment long - //special case: what if the two knots occupy the same segment? - if ((size == 1) || ( size - unsigned(attach_end) - 1 == loc )) - { - Geom::Coord t = Geom::nearest_point(end_attach_point, *curve_start); - - //it is just a dumb segment - //we have to do some shifting here because the value changed when we reduced the length - //of the previous segment. - - order = Outline::bezierOrder(curve_start); - switch (order) { - case 3: { - Geom::CubicBezier *cb = static_cast<Geom::CubicBezier * >(curve_start); - std::pair<Geom::CubicBezier, Geom::CubicBezier> cb_pair = cb->subdivide(t); - trimmed_end.append(cb_pair.second); curve_start = cb_pair.first.duplicate(); - break; - } - case 2: { - Geom::QuadraticBezier *qb = static_cast<Geom::QuadraticBezier * >(curve_start); - std::pair<Geom::QuadraticBezier, Geom::QuadraticBezier> qb_pair = qb->subdivide(t); - trimmed_end.append(qb_pair.second); curve_start = qb_pair.first.duplicate(); - break; - } - case 1: { - Geom::BezierCurveN<1> *lb = static_cast<Geom::BezierCurveN<1> * >(curve_start); - std::pair<Geom::BezierCurveN<1>, Geom::BezierCurveN<1> > lb_pair = lb->subdivide(t); - trimmed_end.append(lb_pair.second); curve_start = lb_pair.first.duplicate(); - break; - } - } - - for (unsigned j = (size - attach_end) + 1; j < size; j++) { - trimmed_end.append(path_in[0] [j]); - } - - path_out.append(*curve_start); - pathv_out.push_back(trimmed_start); - pathv_out.push_back(path_out); - pathv_out.push_back(trimmed_end); - return pathv_out; - } - - pathv_out.push_back(trimmed_start); - - //append almost all of the rest of the path, ignore the curves that the knot is past (we'll get to it in a minute) - path_out.append(*curve_start); - - for (unsigned k = loc + 1; k < (size - unsigned(attach_end)) - 1; k++) { - path_out.append(path_in[0] [k]); - } - - //deal with the last segment in a very similar fashion to the first - loc = size - attach_end; - - Geom::Curve * curve_end = path_in[0] [loc].duplicate(); - - Geom::Coord t = Geom::nearest_point(end_attach_point, *curve_end); - - order = Outline::bezierOrder(curve_end); - switch (order) { - case 3: { - Geom::CubicBezier *cb = static_cast<Geom::CubicBezier * >(curve_end); - std::pair<Geom::CubicBezier, Geom::CubicBezier> cb_pair = cb->subdivide(t); - trimmed_end.append(cb_pair.second); curve_end = cb_pair.first.duplicate(); - break; - } - case 2: { - Geom::QuadraticBezier *qb = static_cast<Geom::QuadraticBezier * >(curve_end); - std::pair<Geom::QuadraticBezier, Geom::QuadraticBezier> qb_pair = qb->subdivide(t); - trimmed_end.append(qb_pair.second); curve_end = qb_pair.first.duplicate(); - break; - } - case 1: { - Geom::BezierCurveN<1> *lb = static_cast<Geom::BezierCurveN<1> * >(curve_end); - std::pair<Geom::BezierCurveN<1>, Geom::BezierCurveN<1> > lb_pair = lb->subdivide(t); - trimmed_end.append(lb_pair.second); curve_end = lb_pair.first.duplicate(); - break; - } - } - - for (unsigned j = (size - attach_end) + 1; j < size; j++) { - trimmed_end.append(path_in[0] [j]); - } - - path_out.append(*curve_end); - pathv_out.push_back(path_out); - - pathv_out.push_back(trimmed_end); - - if (curve_end) delete curve_end; - if (curve_start) delete curve_start; - return pathv_out; + unsigned size = path_in[0].size(); + + //do subdivision and get out + unsigned loc = (unsigned)attach_start; + Geom::Curve * curve_start = path_in[0] [loc].duplicate(); + + std::vector<Geom::Path> pathv_out; + Geom::Path path_out = Geom::Path(); + + Geom::Path trimmed_start = Geom::Path(); + Geom::Path trimmed_end = Geom::Path(); + + for (unsigned i = 0; i < loc; i++) { + trimmed_start.append(path_in[0] [i]); + } + + + //this is pretty annoying + //previously I wrote a function for this but it wasted a lot of time + //so I optimized it back into here. + unsigned order = Outline::bezierOrder(curve_start); + switch (order) { + case 3: { + Geom::CubicBezier *cb = static_cast<Geom::CubicBezier * >(curve_start); + std::pair<Geom::CubicBezier, Geom::CubicBezier> cb_pair = cb->subdivide((attach_start - loc)); + trimmed_start.append(cb_pair.first); + curve_start = cb_pair.second.duplicate(); //goes out of scope + break; + } + case 2: { + Geom::QuadraticBezier *qb = static_cast<Geom::QuadraticBezier * >(curve_start); + std::pair<Geom::QuadraticBezier, Geom::QuadraticBezier> qb_pair = qb->subdivide((attach_start - loc)); + trimmed_start.append(qb_pair.first); + curve_start = qb_pair.second.duplicate(); + break; + } + case 1: { + Geom::BezierCurveN<1> *lb = static_cast<Geom::BezierCurveN<1> * >(curve_start); + std::pair<Geom::BezierCurveN<1>, Geom::BezierCurveN<1> > lb_pair = lb->subdivide((attach_start - loc)); + trimmed_start.append(lb_pair.first); + curve_start = lb_pair.second.duplicate(); + break; + } + } + + //special case: path is one segment long + //special case: what if the two knots occupy the same segment? + if ((size == 1) || ( size - unsigned(attach_end) - 1 == loc )) { + Geom::Coord t = Geom::nearest_point(end_attach_point, *curve_start); + + //it is just a dumb segment + //we have to do some shifting here because the value changed when we reduced the length + //of the previous segment. + + order = Outline::bezierOrder(curve_start); + switch (order) { + case 3: { + Geom::CubicBezier *cb = static_cast<Geom::CubicBezier * >(curve_start); + std::pair<Geom::CubicBezier, Geom::CubicBezier> cb_pair = cb->subdivide(t); + trimmed_end.append(cb_pair.second); + curve_start = cb_pair.first.duplicate(); + break; + } + case 2: { + Geom::QuadraticBezier *qb = static_cast<Geom::QuadraticBezier * >(curve_start); + std::pair<Geom::QuadraticBezier, Geom::QuadraticBezier> qb_pair = qb->subdivide(t); + trimmed_end.append(qb_pair.second); + curve_start = qb_pair.first.duplicate(); + break; + } + case 1: { + Geom::BezierCurveN<1> *lb = static_cast<Geom::BezierCurveN<1> * >(curve_start); + std::pair<Geom::BezierCurveN<1>, Geom::BezierCurveN<1> > lb_pair = lb->subdivide(t); + trimmed_end.append(lb_pair.second); + curve_start = lb_pair.first.duplicate(); + break; + } + } + + for (unsigned j = (size - attach_end) + 1; j < size; j++) { + trimmed_end.append(path_in[0] [j]); + } + + path_out.append(*curve_start); + pathv_out.push_back(trimmed_start); + pathv_out.push_back(path_out); + pathv_out.push_back(trimmed_end); + return pathv_out; + } + + pathv_out.push_back(trimmed_start); + + //append almost all of the rest of the path, ignore the curves that the knot is past (we'll get to it in a minute) + path_out.append(*curve_start); + + for (unsigned k = loc + 1; k < (size - unsigned(attach_end)) - 1; k++) { + path_out.append(path_in[0] [k]); + } + + //deal with the last segment in a very similar fashion to the first + loc = size - attach_end; + + Geom::Curve * curve_end = path_in[0] [loc].duplicate(); + + Geom::Coord t = Geom::nearest_point(end_attach_point, *curve_end); + + order = Outline::bezierOrder(curve_end); + switch (order) { + case 3: { + Geom::CubicBezier *cb = static_cast<Geom::CubicBezier * >(curve_end); + std::pair<Geom::CubicBezier, Geom::CubicBezier> cb_pair = cb->subdivide(t); + trimmed_end.append(cb_pair.second); + curve_end = cb_pair.first.duplicate(); + break; + } + case 2: { + Geom::QuadraticBezier *qb = static_cast<Geom::QuadraticBezier * >(curve_end); + std::pair<Geom::QuadraticBezier, Geom::QuadraticBezier> qb_pair = qb->subdivide(t); + trimmed_end.append(qb_pair.second); + curve_end = qb_pair.first.duplicate(); + break; + } + case 1: { + Geom::BezierCurveN<1> *lb = static_cast<Geom::BezierCurveN<1> * >(curve_end); + std::pair<Geom::BezierCurveN<1>, Geom::BezierCurveN<1> > lb_pair = lb->subdivide(t); + trimmed_end.append(lb_pair.second); + curve_end = lb_pair.first.duplicate(); + break; + } + } + + for (unsigned j = (size - attach_end) + 1; j < size; j++) { + trimmed_end.append(path_in[0] [j]); + } + + path_out.append(*curve_end); + pathv_out.push_back(path_out); + + pathv_out.push_back(trimmed_end); + + if (curve_end) delete curve_end; + if (curve_start) delete curve_start; + return pathv_out; } @@ -509,14 +523,14 @@ Geom::PathVector LPETaperStroke::doEffect_simplePath(Geom::PathVector const & pa //tweaking to get it to work right in this case. Geom::Piecewise<Geom::D2<Geom::SBasis> > stretch_along(Geom::Piecewise<Geom::D2<Geom::SBasis> > pwd2_in, Geom::Path pattern, double prop_scale) { - using namespace Geom; + using namespace Geom; // Don't allow empty path parameter: if ( pattern.empty() ) { return pwd2_in; } -/* Much credit should go to jfb and mgsloan of lib2geom development for the code below! */ + /* Much credit should go to jfb and mgsloan of lib2geom development for the code below! */ Piecewise<D2<SBasis> > output; std::vector<Geom::Piecewise<Geom::D2<Geom::SBasis> > > pre_output; @@ -548,7 +562,7 @@ Geom::Piecewise<Geom::D2<Geom::SBasis> > stretch_along(Geom::Piecewise<Geom::D2< std::vector<Geom::Piecewise<Geom::D2<Geom::SBasis> > > paths_in; paths_in = split_at_discontinuities(pwd2_in); - for (unsigned idx = 0; idx < paths_in.size(); idx++){ + for (unsigned idx = 0; idx < paths_in.size(); idx++) { Geom::Piecewise<Geom::D2<Geom::SBasis> > path_i = paths_in[idx]; Piecewise<SBasis> x = x0; Piecewise<SBasis> y = y0; @@ -556,14 +570,14 @@ Geom::Piecewise<Geom::D2<Geom::SBasis> > stretch_along(Geom::Piecewise<Geom::D2< uskeleton = remove_short_cuts(uskeleton,.01); Piecewise<D2<SBasis> > n = rot90(derivative(uskeleton)); n = force_continuity(remove_short_cuts(n,.1)); - + int nbCopies = 0; double scaling = 1; nbCopies = 1; scaling = (uskeleton.domain().extent() - toffset)/pattBndsX->extent(); double pattWidth = pattBndsX->extent() * scaling; - + if (scaling != 1.0) { x*=scaling; } @@ -573,20 +587,20 @@ Geom::Piecewise<Geom::D2<Geom::SBasis> > stretch_along(Geom::Piecewise<Geom::D2< if (prop_scale != 1.0) y *= prop_scale; } x += toffset; - + double offs = 0; - for (int i=0; i<nbCopies; i++){ - if (false){ + for (int i=0; i<nbCopies; i++) { + if (false) { Geom::Piecewise<Geom::D2<Geom::SBasis> > output_piece = compose(uskeleton,x+offs)+y*compose(n,x+offs); std::vector<Geom::Piecewise<Geom::D2<Geom::SBasis> > > splited_output_piece = split_at_discontinuities(output_piece); pre_output.insert(pre_output.end(), splited_output_piece.begin(), splited_output_piece.end() ); - }else{ + } else { output.concat(compose(uskeleton,x+offs)+y*compose(n,x+offs)); } offs+=pattWidth; } } - /*if (false){ + /*if (false){ pre_output = fuse_nearby_ends(pre_output, fuse_tolerance); for (unsigned i=0; i<pre_output.size(); i++){ output.concat(pre_output[i]); @@ -598,76 +612,107 @@ Geom::Piecewise<Geom::D2<Geom::SBasis> > stretch_along(Geom::Piecewise<Geom::D2< } } +void subdivideCurve(Geom::Curve * curve_in, Geom::Coord t, Geom::Curve *& val_first, Geom::Curve *& val_second) +{ + unsigned order = Outline::bezierOrder(curve_in); + switch (order) { + case 3: { + Geom::CubicBezier *cb = static_cast<Geom::CubicBezier * >(curve_in); + std::pair<Geom::CubicBezier, Geom::CubicBezier> cb_pair = cb->subdivide(t); + //trimmed_start.append(cb_pair.first); + val_first = cb_pair.first.duplicate(); + val_second = cb_pair.second.duplicate(); + break; + } + case 2: { + Geom::QuadraticBezier *qb = static_cast<Geom::QuadraticBezier * >(curve_in); + std::pair<Geom::QuadraticBezier, Geom::QuadraticBezier> qb_pair = qb->subdivide(t); + //trimmed_start.append(qb_pair.first); + val_first = qb_pair.first.duplicate(); + val_second = qb_pair.second.duplicate(); + break; + } + case 1: { + Geom::BezierCurveN<1> *lb = static_cast<Geom::BezierCurveN<1> * >(curve_in); + std::pair<Geom::BezierCurveN<1>, Geom::BezierCurveN<1> > lb_pair = lb->subdivide(t); + //trimmed_start.append(lb_pair.first); + val_first = lb_pair.first.duplicate(); + val_second = lb_pair.second.duplicate(); + break; + } + } +} -void LPETaperStroke::addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item) + +void LPETaperStroke::addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item) { - { - KnotHolderEntity *e = new TpS::KnotHolderEntityAttachBegin(this); - e->create( desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN, - _("Start point of the taper"), SP_KNOT_SHAPE_CIRCLE ); - knotholder->add(e); - } - { - KnotHolderEntity *e = new TpS::KnotHolderEntityAttachEnd(this); - e->create( desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN, - _("End point of the taper"), SP_KNOT_SHAPE_CIRCLE ); - knotholder->add(e); - } + { + KnotHolderEntity *e = new TpS::KnotHolderEntityAttachBegin(this); + e->create( desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN, + _("Start point of the taper"), SP_KNOT_SHAPE_CIRCLE ); + knotholder->add(e); + } + { + KnotHolderEntity *e = new TpS::KnotHolderEntityAttachEnd(this); + e->create( desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN, + _("End point of the taper"), SP_KNOT_SHAPE_CIRCLE ); + knotholder->add(e); + } } namespace TpS { - void KnotHolderEntityAttachBegin::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state) - { - using namespace Geom; - - LPETaperStroke* lpe = dynamic_cast<LPETaperStroke *>(_effect); - - Geom::Point const s = snap_knot_position(p, state); - - SPCurve *curve = SP_PATH(item)->get_curve_for_edit(); - Geom::PathVector pathv = curve->get_pathvector(); - Piecewise<D2<SBasis> > pwd2; - Geom::Path p_in = return_at_first_cusp(pathv[0]); - pwd2.concat(p_in.toPwSb()); - std::vector<Geom::Piecewise<Geom::D2<Geom::SBasis> > > pwd_vec = split_at_discontinuities(pwd2); - - double t0 = nearest_point(s, pwd_vec[0]); - lpe->attach_start.param_set_value(t0); - - // FIXME: this should not directly ask for updating the item. It should write to SVG, which triggers updating. - sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), false, true); - } - void KnotHolderEntityAttachEnd::knot_set(Geom::Point const &p, Geom::Point const& /*origin*/, guint state) - { - using namespace Geom; - - LPETaperStroke* lpe = dynamic_cast<LPETaperStroke *>(_effect); - - Geom::Point const s = snap_knot_position(p, state); - - SPCurve *curve = SP_PATH(item)->get_curve_for_edit(); - Geom::PathVector pathv = curve->get_pathvector(); - Piecewise<D2<SBasis> > pwd2; - Geom::Path p_in = return_at_first_cusp(pathv[0].reverse()); - pwd2.concat(p_in.toPwSb()); - std::vector<Geom::Piecewise<Geom::D2<Geom::SBasis> > > pwd_vec = split_at_discontinuities(pwd2); - - double t0 = nearest_point(s, pwd_vec[0]); - lpe->attach_end.param_set_value(t0); - - // FIXME: this should not directly ask for updating the item. It should write to SVG, which triggers updating. - sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), false, true); - } - Geom::Point KnotHolderEntityAttachBegin::knot_get() const - { - LPETaperStroke const * lpe = dynamic_cast<LPETaperStroke const*> (_effect); - return lpe->start_attach_point; - } - Geom::Point KnotHolderEntityAttachEnd::knot_get() const - { - LPETaperStroke const * lpe = dynamic_cast<LPETaperStroke const*> (_effect); - return lpe->end_attach_point; - } +void KnotHolderEntityAttachBegin::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state) +{ + using namespace Geom; + + LPETaperStroke* lpe = dynamic_cast<LPETaperStroke *>(_effect); + + Geom::Point const s = snap_knot_position(p, state); + + SPCurve *curve = SP_PATH(item)->get_curve_for_edit(); + Geom::PathVector pathv = curve->get_pathvector(); + Piecewise<D2<SBasis> > pwd2; + Geom::Path p_in = return_at_first_cusp(pathv[0]); + pwd2.concat(p_in.toPwSb()); + std::vector<Geom::Piecewise<Geom::D2<Geom::SBasis> > > pwd_vec = split_at_discontinuities(pwd2); + + double t0 = nearest_point(s, pwd_vec[0]); + lpe->attach_start.param_set_value(t0); + + // FIXME: this should not directly ask for updating the item. It should write to SVG, which triggers updating. + sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), false, true); +} +void KnotHolderEntityAttachEnd::knot_set(Geom::Point const &p, Geom::Point const& /*origin*/, guint state) +{ + using namespace Geom; + + LPETaperStroke* lpe = dynamic_cast<LPETaperStroke *>(_effect); + + Geom::Point const s = snap_knot_position(p, state); + + SPCurve *curve = SP_PATH(item)->get_curve_for_edit(); + Geom::PathVector pathv = curve->get_pathvector(); + Piecewise<D2<SBasis> > pwd2; + Geom::Path p_in = return_at_first_cusp(pathv[0].reverse()); + pwd2.concat(p_in.toPwSb()); + std::vector<Geom::Piecewise<Geom::D2<Geom::SBasis> > > pwd_vec = split_at_discontinuities(pwd2); + + double t0 = nearest_point(s, pwd_vec[0]); + lpe->attach_end.param_set_value(t0); + + // FIXME: this should not directly ask for updating the item. It should write to SVG, which triggers updating. + sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), false, true); +} +Geom::Point KnotHolderEntityAttachBegin::knot_get() const +{ + LPETaperStroke const * lpe = dynamic_cast<LPETaperStroke const*> (_effect); + return lpe->start_attach_point; +} +Geom::Point KnotHolderEntityAttachEnd::knot_get() const +{ + LPETaperStroke const * lpe = dynamic_cast<LPETaperStroke const*> (_effect); + return lpe->end_attach_point; +} } diff --git a/src/live_effects/lpe-taperstroke.h b/src/live_effects/lpe-taperstroke.h index 29a56f77c..997209543 100644 --- a/src/live_effects/lpe-taperstroke.h +++ b/src/live_effects/lpe-taperstroke.h @@ -20,39 +20,39 @@ namespace Inkscape { namespace LivePathEffect { namespace TpS { - // we need a separate namespace to avoid clashes with other LPEs - class KnotHolderEntityAttachBegin; - class KnotHolderEntityAttachEnd; +// we need a separate namespace to avoid clashes with other LPEs +class KnotHolderEntityAttachBegin; +class KnotHolderEntityAttachEnd; } class LPETaperStroke : public Effect { public: - LPETaperStroke(LivePathEffectObject *lpeobject); - virtual ~LPETaperStroke(); - - virtual void doOnApply(SPLPEItem const* lpeitem); - virtual void doOnRemove(SPLPEItem const* lpeitem); + LPETaperStroke(LivePathEffectObject *lpeobject); + virtual ~LPETaperStroke(); - virtual Geom::PathVector doEffect_path (Geom::PathVector const& path_in); - Geom::PathVector doEffect_simplePath(Geom::PathVector const& path_in); - - virtual void addKnotHolderEntities(KnotHolder * knotholder, SPDesktop * desktop, SPItem * item); + virtual void doOnApply(SPLPEItem const* lpeitem); + virtual void doOnRemove(SPLPEItem const* lpeitem); - friend class TpS::KnotHolderEntityAttachBegin; - friend class TpS::KnotHolderEntityAttachEnd; + virtual Geom::PathVector doEffect_path (Geom::PathVector const& path_in); + Geom::PathVector doEffect_simplePath(Geom::PathVector const& path_in); + + virtual void addKnotHolderEntities(KnotHolder * knotholder, SPDesktop * desktop, SPItem * item); + + friend class TpS::KnotHolderEntityAttachBegin; + friend class TpS::KnotHolderEntityAttachEnd; private: - ScalarParam line_width; - ScalarParam attach_start; - ScalarParam attach_end; - ScalarParam smoothing; - EnumParam<unsigned> join_type; - ScalarParam miter_limit; + ScalarParam line_width; + ScalarParam attach_start; + ScalarParam attach_end; + ScalarParam smoothing; + EnumParam<unsigned> join_type; + ScalarParam miter_limit; - Geom::Point start_attach_point; - Geom::Point end_attach_point; + Geom::Point start_attach_point; + Geom::Point end_attach_point; - LPETaperStroke(const LPETaperStroke&); - LPETaperStroke& operator=(const LPETaperStroke&); + LPETaperStroke(const LPETaperStroke&); + LPETaperStroke& operator=(const LPETaperStroke&); }; } //namespace LivePathEffect diff --git a/src/live_effects/pathoutlineprovider.cpp b/src/live_effects/pathoutlineprovider.cpp index 6a47285a0..ad39a7416 100755..100644 --- a/src/live_effects/pathoutlineprovider.cpp +++ b/src/live_effects/pathoutlineprovider.cpp @@ -9,133 +9,128 @@ #include <2geom/path-sink.h>
#include <svg/svg.h>
-namespace Geom
+namespace Geom {
+/**
+* Refer to: Weisstein, Eric W. "Circle-Circle Intersection."
+ From MathWorld--A Wolfram Web Resource.
+ http://mathworld.wolfram.com/Circle-CircleIntersection.html
+*
+* @return 0 if no intersection
+* @return 1 if one circle is contained in the other
+* @return 2 if intersections are found (they are written to p0 and p1)
+*/
+static int circle_circle_intersection(Circle const &circle0, Circle const &circle1,
+ Point & p0, Point & p1)
+{
+ Point X0 = circle0.center();
+ double r0 = circle0.ray();
+ Point X1 = circle1.center();
+ double r1 = circle1.ray();
+
+ /* dx and dy are the vertical and horizontal distances between
+ * the circle centers.
+ */
+ Point D = X1 - X0;
+
+ /* Determine the straight-line distance between the centers. */
+ double d = L2(D);
+
+ /* Check for solvability. */
+ if (d > (r0 + r1)) {
+ /* no solution. circles do not intersect. */
+ return 0;
+ }
+ if (d <= fabs(r0 - r1)) {
+ /* no solution. one circle is contained in the other */
+ return 1;
+ }
+
+ /* 'point 2' is the point where the line through the circle
+ * intersection points crosses the line between the circle
+ * centers.
+ */
+
+ /* Determine the distance from point 0 to point 2. */
+ double a = ((r0*r0) - (r1*r1) + (d*d)) / (2.0 * d) ;
+
+ /* Determine the coordinates of point 2. */
+ Point p2 = X0 + D * (a/d);
+
+ /* Determine the distance from point 2 to either of the
+ * intersection points.
+ */
+ double h = std::sqrt((r0*r0) - (a*a));
+
+ /* Now determine the offsets of the intersection points from
+ * point 2.
+ */
+ Point r = (h/d)*rot90(D);
+
+ /* Determine the absolute intersection points. */
+ p0 = p2 + r;
+ p1 = p2 - r;
+
+ return 2;
+}
+/**
+* Find circle that touches inside of the curve, with radius matching the curvature, at time value \c t.
+* Because this method internally uses unitTangentAt, t should be smaller than 1.0 (see unitTangentAt).
+*/
+static Circle touching_circle( D2<SBasis> const &curve, double t, double tol=0.01 )
{
- /**
- * Refer to: Weisstein, Eric W. "Circle-Circle Intersection."
- From MathWorld--A Wolfram Web Resource.
- http://mathworld.wolfram.com/Circle-CircleIntersection.html
- *
- * @return 0 if no intersection
- * @return 1 if one circle is contained in the other
- * @return 2 if intersections are found (they are written to p0 and p1)
- */
- static int circle_circle_intersection(Circle const &circle0, Circle const &circle1,
- Point & p0, Point & p1)
- {
- Point X0 = circle0.center();
- double r0 = circle0.ray();
- Point X1 = circle1.center();
- double r1 = circle1.ray();
-
- /* dx and dy are the vertical and horizontal distances between
- * the circle centers.
- */
- Point D = X1 - X0;
-
- /* Determine the straight-line distance between the centers. */
- double d = L2(D);
-
- /* Check for solvability. */
- if (d > (r0 + r1))
- {
- /* no solution. circles do not intersect. */
- return 0;
- }
- if (d <= fabs(r0 - r1))
- {
- /* no solution. one circle is contained in the other */
- return 1;
- }
-
- /* 'point 2' is the point where the line through the circle
- * intersection points crosses the line between the circle
- * centers.
- */
-
- /* Determine the distance from point 0 to point 2. */
- double a = ((r0*r0) - (r1*r1) + (d*d)) / (2.0 * d) ;
-
- /* Determine the coordinates of point 2. */
- Point p2 = X0 + D * (a/d);
-
- /* Determine the distance from point 2 to either of the
- * intersection points.
- */
- double h = std::sqrt((r0*r0) - (a*a));
-
- /* Now determine the offsets of the intersection points from
- * point 2.
- */
- Point r = (h/d)*rot90(D);
-
- /* Determine the absolute intersection points. */
- p0 = p2 + r;
- p1 = p2 - r;
-
- return 2;
- }
- /**
- * Find circle that touches inside of the curve, with radius matching the curvature, at time value \c t.
- * Because this method internally uses unitTangentAt, t should be smaller than 1.0 (see unitTangentAt).
- */
- static Circle touching_circle( D2<SBasis> const &curve, double t, double tol=0.01 )
- {
- D2<SBasis> dM=derivative(curve);
- if ( are_near(L2sq(dM(t)),0.) ) {
- dM=derivative(dM);
- }
- if ( are_near(L2sq(dM(t)),0.) ) { // try second time
- dM=derivative(dM);
- }
- Piecewise<D2<SBasis> > unitv = unitVector(dM,tol);
- Piecewise<SBasis> dMlength = dot(Piecewise<D2<SBasis> >(dM),unitv);
- Piecewise<SBasis> k = cross(derivative(unitv),unitv);
- k = divide(k,dMlength,tol,3);
- double curv = k(t); // note that this value is signed
-
- Geom::Point normal = unitTangentAt(curve, t).cw();
- double radius = 1/curv;
- Geom::Point center = curve(t) + radius*normal;
- return Geom::Circle(center, fabs(radius));
- }
-
- static std::vector<Geom::Path> split_at_cusps(const Geom::Path& in)
- {
- Geom::PathVector out = Geom::PathVector();
- Geom::Path temp = Geom::Path();
-
- for (unsigned path_descr = 0; path_descr < in.size(); path_descr++)
- {
- temp = Geom::Path();
- temp.append(in[path_descr]);
- out.push_back(temp);
- }
-
- return out;
- }
-
- static Geom::CubicBezier sbasis_to_cubicbezier(Geom::D2<Geom::SBasis> const & sbasis_in)
- {
- std::vector<Geom::Point> temp;
- sbasis_to_bezier(temp, sbasis_in, 4);
- return Geom::CubicBezier( temp );
- }
-
- static boost::optional<Geom::Point> intersection_point( Geom::Point const & origin_a, Geom::Point const & vector_a,
- Geom::Point const & origin_b, Geom::Point const & vector_b)
- {
- Geom::Coord denom = cross(vector_b, vector_a);
- if (!Geom::are_near(denom,0.)){
- Geom::Coord t = (cross(origin_a,vector_b) + cross(vector_b,origin_b)) / denom;
- return origin_a + t * vector_a;
- }
- return boost::none;
- }
+ D2<SBasis> dM=derivative(curve);
+ if ( are_near(L2sq(dM(t)),0.) ) {
+ dM=derivative(dM);
+ }
+ if ( are_near(L2sq(dM(t)),0.) ) { // try second time
+ dM=derivative(dM);
+ }
+ Piecewise<D2<SBasis> > unitv = unitVector(dM,tol);
+ Piecewise<SBasis> dMlength = dot(Piecewise<D2<SBasis> >(dM),unitv);
+ Piecewise<SBasis> k = cross(derivative(unitv),unitv);
+ k = divide(k,dMlength,tol,3);
+ double curv = k(t); // note that this value is signed
+
+ Geom::Point normal = unitTangentAt(curve, t).cw();
+ double radius = 1/curv;
+ Geom::Point center = curve(t) + radius*normal;
+ return Geom::Circle(center, fabs(radius));
}
-namespace Outline
+static std::vector<Geom::Path> split_at_cusps(const Geom::Path& in)
{
+ Geom::PathVector out = Geom::PathVector();
+ Geom::Path temp = Geom::Path();
+
+ for (unsigned path_descr = 0; path_descr < in.size(); path_descr++) {
+ temp = Geom::Path();
+ temp.append(in[path_descr]);
+ out.push_back(temp);
+ }
+
+ return out;
+}
+
+static Geom::CubicBezier sbasis_to_cubicbezier(Geom::D2<Geom::SBasis> const & sbasis_in)
+{
+ std::vector<Geom::Point> temp;
+ sbasis_to_bezier(temp, sbasis_in, 4);
+ return Geom::CubicBezier( temp );
+}
+
+static boost::optional<Geom::Point> intersection_point( Geom::Point const & origin_a, Geom::Point const & vector_a,
+ Geom::Point const & origin_b, Geom::Point const & vector_b)
+{
+ Geom::Coord denom = cross(vector_b, vector_a);
+ if (!Geom::are_near(denom,0.)) {
+ Geom::Coord t = (cross(origin_a,vector_b) + cross(vector_b,origin_b)) / denom;
+ return origin_a + t * vector_a;
+ }
+ return boost::none;
+}
+}
+
+namespace Outline {
typedef Geom::D2<Geom::SBasis> D2SB;
typedef Geom::Piecewise<D2SB> PWD2;
@@ -160,72 +155,70 @@ bool outside_angle (const Geom::Curve& cbc1, const Geom::Curve& cbc2) unsigned order = bezierOrder(&cbc1);
Geom::Point start_point;
- Geom::Point cross_point = cbc1.finalPoint();
- Geom::Point end_point;
-
- //assert(cbc1.finalPoint() == cbc2.initialPoint());
- //short circuiting?
- if (cbc1.finalPoint() != cbc2.initialPoint()) {
- printf("There was an issue when asserting that one curve's end is the start of the other. Line %d, File %s\n"
- "By default we are going to say that this is an inside join, so we cannot make a line join for it.\n", __LINE__, __FILE__);
- return false;
+ Geom::Point cross_point = cbc1.finalPoint();
+ Geom::Point end_point;
+
+ //assert(cbc1.finalPoint() == cbc2.initialPoint());
+ //short circuiting?
+ if (cbc1.finalPoint() != cbc2.initialPoint()) {
+ printf("There was an issue when asserting that one curve's end is the start of the other. Line %d, File %s\n"
+ "By default we are going to say that this is an inside join, so we cannot make a line join for it.\n", __LINE__, __FILE__);
+ return false;
+ }
+ switch (order) {
+ case 3:
+ start_point = (static_cast<const Geom::CubicBezier*>(&cbc1))->operator[] (2);
+ //major league b***f***ing
+ if (are_near(start_point, cross_point, 0.0000001)) {
+ start_point = (static_cast<const Geom::CubicBezier*>(&cbc1))->operator[] (1);
}
- switch (order)
- {
- case 3:
- start_point = (static_cast<const Geom::CubicBezier*>(&cbc1))->operator[] (2);
- //major league b***f***ing
- if (are_near(start_point, cross_point, 0.0000001)) {
- start_point = (static_cast<const Geom::CubicBezier*>(&cbc1))->operator[] (1);
- }
- break;
- case 2:
- //this never happens
- start_point = (static_cast<const Geom::QuadraticBezier*>(&cbc1))->operator[] (1);
- break;
- case 1:
- default:
- start_point = cbc1.initialPoint();
- }
-
- order = Outline::bezierOrder(&cbc2);
-
- switch (order)
- {
- case 3:
- end_point = (static_cast<const Geom::CubicBezier*>(&cbc2))->operator[] (1);
- if (are_near(end_point, cross_point, 0.0000001)) {
- end_point = (static_cast<const Geom::CubicBezier*>(&cbc2))->operator[] (2);
- }
- break;
- case 2:
- end_point = (static_cast<const Geom::QuadraticBezier*>(&cbc2))->operator[] (1);
- break;
- case 1:
- default:
- end_point = cbc2.finalPoint();
- }
- //got our three points, now let's see what their clockwise angle is
-
- //Much credit to Wikipedia for the following ( http://en.wikipedia.org/wiki/Graham_scan )
- /********************************************************************
+ break;
+ case 2:
+ //this never happens
+ start_point = (static_cast<const Geom::QuadraticBezier*>(&cbc1))->operator[] (1);
+ break;
+ case 1:
+ default:
+ start_point = cbc1.initialPoint();
+ }
+
+ order = Outline::bezierOrder(&cbc2);
+
+ switch (order) {
+ case 3:
+ end_point = (static_cast<const Geom::CubicBezier*>(&cbc2))->operator[] (1);
+ if (are_near(end_point, cross_point, 0.0000001)) {
+ end_point = (static_cast<const Geom::CubicBezier*>(&cbc2))->operator[] (2);
+ }
+ break;
+ case 2:
+ end_point = (static_cast<const Geom::QuadraticBezier*>(&cbc2))->operator[] (1);
+ break;
+ case 1:
+ default:
+ end_point = cbc2.finalPoint();
+ }
+ //got our three points, now let's see what their clockwise angle is
+
+ //Much credit to Wikipedia for the following ( http://en.wikipedia.org/wiki/Graham_scan )
+ /********************************************************************
# Three points are a counter-clockwise turn if ccw > 0, clockwise if
# ccw < 0, and collinear if ccw = 0 because ccw is a determinant that
# gives the signed area of the triangle formed by p1, p2 and p3.
function ccw(p1, p2, p3):
- return (p2.x - p1.x)*(p3.y - p1.y) - (p2.y - p1.y)*(p3.x - p1.x)
+ return (p2.x - p1.x)*(p3.y - p1.y) - (p2.y - p1.y)*(p3.x - p1.x)
*********************************************************************/
-
+
double ccw = ( (cross_point.x() - start_point.x()) * (end_point.y() - start_point.y()) ) -
( (cross_point.y() - start_point.y()) * (end_point.x() - start_point.x()) );
if (ccw > 0) return true;
return false;
}
-void extrapolate_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve* cbc2, Geom::Point endPt,
+void extrapolate_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve* cbc2, Geom::Point endPt,
double miter_limit, double line_width, bool outside = false)
{
- bool lineProblem = (dynamic_cast<Geom::BezierCurveN<1u> *>(cbc1)) || (dynamic_cast<Geom::BezierCurveN<1u> *>(cbc2));
+ bool lineProblem = (dynamic_cast<Geom::BezierCurveN<1u> *>(cbc1)) || (dynamic_cast<Geom::BezierCurveN<1u> *>(cbc2));
if ( outside && !lineProblem ) {
Geom::Path pth;
pth.append(*cbc1);
@@ -271,9 +264,8 @@ void extrapolate_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve }
} else {
boost::optional <Geom::Point> p = intersection_point (cbc1->finalPoint(), tang1,
- cbc2->initialPoint(), tang2);
- if (p)
- {
+ cbc2->initialPoint(), tang2);
+ if (p) {
//check size of miter
Geom::Point point_on_path = cbc1->finalPoint() - rot90(tang1) * line_width;
Geom::Coord len = distance(*p, point_on_path);
@@ -284,19 +276,18 @@ void extrapolate_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve }
path_builder.appendNew<Geom::LineSegment> (endPt);
}
- }
- if ( outside && lineProblem ) {
- Geom::Path pth;
+ }
+ if ( outside && lineProblem ) {
+ Geom::Path pth;
pth.append(*cbc1);
- Geom::Point tang1 = Geom::unitTangentAt(Geom::reverse(pth.toPwSb()[0]), 0.);
+ Geom::Point tang1 = Geom::unitTangentAt(Geom::reverse(pth.toPwSb()[0]), 0.);
pth = Geom::Path();
- pth.append( *cbc2 );
- Geom::Point tang2 = Geom::unitTangentAt(pth.toPwSb()[0], 0);
-
- boost::optional <Geom::Point> p = intersection_point (cbc1->finalPoint(), tang1,
- cbc2->initialPoint(), tang2);
- if (p)
- {
+ pth.append( *cbc2 );
+ Geom::Point tang2 = Geom::unitTangentAt(pth.toPwSb()[0], 0);
+
+ boost::optional <Geom::Point> p = intersection_point (cbc1->finalPoint(), tang1,
+ cbc2->initialPoint(), tang2);
+ if (p) {
//check size of miter
Geom::Point point_on_path = cbc1->finalPoint() - rot90(tang1) * line_width;
Geom::Coord len = distance(*p, point_on_path);
@@ -306,13 +297,13 @@ void extrapolate_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve }
}
path_builder.appendNew<Geom::LineSegment> (endPt);
- }
- if ( !outside ) {
- path_builder.appendNew<Geom::LineSegment> (endPt);
- }
+ }
+ if ( !outside ) {
+ path_builder.appendNew<Geom::LineSegment> (endPt);
+ }
}
-void reflect_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve* cbc2, Geom::Point endPt,
+void reflect_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve* cbc2, Geom::Point endPt,
double miter_limit, double line_width, bool outside = false)
{
//the most important work for the reflected join is done here
@@ -320,7 +311,7 @@ void reflect_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve* cb //determine where we are in the path. If we're on the inside, ignore
//and just lineTo. On the outside, we'll do a little reflection magic :)
Geom::Crossings cross;
-
+
if (outside) {
Geom::Path pth;
pth.append(*cbc1);
@@ -347,9 +338,8 @@ void reflect_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve* cb if ( cross.empty() ) {
//curves didn't cross; default to miter
boost::optional <Geom::Point> p = intersection_point (cbc1->finalPoint(), tang1,
- cbc2->initialPoint(), tang2);
- if (p)
- {
+ cbc2->initialPoint(), tang2);
+ if (p) {
//check size of miter
Geom::Point point_on_path = cbc1->finalPoint() - rot90(tang1) * line_width;
Geom::Coord len = distance(*p, point_on_path);
@@ -388,27 +378,26 @@ Geom::Path doAdvHalfOutline(const Geom::Path& path_in, double line_width, double // NOTE: it is important to notice the distinction between a Geom::Path and a livarot Path here!
// if you do not see "Geom::" there is a different function set!
Geom::PathVector pv = split_at_cusps(path_in);
-
+
Path to_outline;
Path outlined_result;
-
+
Geom::Path path_builder = Geom::Path(); //the path to store the result in
Geom::PathVector * path_vec; //needed because livarot returns a goddamn pointer
-
+
const unsigned k = path_in.size();
-
- for (unsigned u = 0; u < k; u+=2)
- {
+
+ for (unsigned u = 0; u < k; u+=2) {
to_outline = Path();
outlined_result = Path();
-
+
to_outline.LoadPath(pv[u], Geom::Affine(), false, false);
to_outline.OutsideOutline(&outlined_result, line_width / 2, join_straight, butt_straight, 10);
//now a curve has been outside outlined and loaded into outlined_result
-
+
//get the Geom::Path
path_vec = outlined_result.MakePathVector();
-
+
//thing to do on the first run through
if (u == 0) {
//I could use the pv->operator[] (0) notation but that looks terrible
@@ -417,58 +406,64 @@ Geom::Path doAdvHalfOutline(const Geom::Path& path_in, double line_width, double //get the curves ready for the operation
Geom::Curve * cbc1 = path_builder[path_builder.size() - 1].duplicate();
Geom::Curve * cbc2 = (*path_vec)[0] [0].duplicate();
-
+
//do the reflection/extrapolation:
- if (extrapolate) { extrapolate_curves(path_builder, cbc1, cbc2, (*path_vec)[0].initialPoint(), miter_limit, line_width,
- outside_angle ( pv[u - 1] [pv[u - 1].size() - 1], pv[u] [0] )); }
- else { reflect_curves (path_builder, cbc1, cbc2, (*path_vec)[0].initialPoint(), miter_limit, line_width,
- outside_angle ( pv[u - 1] [pv[u - 1].size() - 1], pv[u] [0] )); }
+ if (extrapolate) {
+ extrapolate_curves(path_builder, cbc1, cbc2, (*path_vec)[0].initialPoint(), miter_limit, line_width,
+ outside_angle ( pv[u - 1] [pv[u - 1].size() - 1], pv[u] [0] ));
+ } else {
+ reflect_curves (path_builder, cbc1, cbc2, (*path_vec)[0].initialPoint(), miter_limit, line_width,
+ outside_angle ( pv[u - 1] [pv[u - 1].size() - 1], pv[u] [0] ));
+ }
}
-
+
path_builder.append( (*path_vec)[0] );
-
+
//outline the next segment, but don't store it yet
if (path_vec) delete path_vec;
-
+
if (u < k - 1) {
outlined_result = Path();
to_outline = Path();
-
+
to_outline.LoadPath(pv[u+1], Geom::Affine(), false, false);
to_outline.OutsideOutline(&outlined_result, line_width / 2, join_straight, butt_straight, 10);
-
+
path_vec = outlined_result.MakePathVector();
-
+
//get the curves ready for the operation
Geom::Curve * cbc1 = path_builder[path_builder.size() - 1].duplicate();
Geom::Curve * cbc2 = (*path_vec)[0] [0].duplicate();
-
+
//do the reflection/extrapolation:
- if (extrapolate) { extrapolate_curves(path_builder, cbc1, cbc2, (*path_vec)[0].initialPoint(), miter_limit, line_width,
- outside_angle ( pv[u] [pv[u].size()-1], pv[u+1] [0] )); }
- else { reflect_curves (path_builder, cbc1, cbc2, (*path_vec)[0].initialPoint(), miter_limit, line_width,
- outside_angle ( pv[u] [pv[u].size()-1], pv[u+1] [0] )); }
-
+ if (extrapolate) {
+ extrapolate_curves(path_builder, cbc1, cbc2, (*path_vec)[0].initialPoint(), miter_limit, line_width,
+ outside_angle ( pv[u] [pv[u].size()-1], pv[u+1] [0] ));
+ } else {
+ reflect_curves (path_builder, cbc1, cbc2, (*path_vec)[0].initialPoint(), miter_limit, line_width,
+ outside_angle ( pv[u] [pv[u].size()-1], pv[u+1] [0] ));
+ }
+
//Now we can store it.
path_builder.append( (*path_vec)[0] );
-
+
if (cbc1) delete cbc1;
if (cbc2) delete cbc2;
if (path_vec) delete path_vec;
}
}
-
+
return path_builder;
}
-Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, LineJoinType join,
+Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, LineJoinType join,
ButtType butt, double miter_lim, bool extrapolate)
{
Geom::PathVector path_out;
-
+
unsigned pv_size = path_in.size();
for (unsigned i = 0; i < pv_size; i++) {
-
+
if (path_in[i].size() > 1) {
//since you've made it this far, hopefully all this is obvious :P
Geom::Path with_direction;
@@ -484,8 +479,8 @@ Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, newPath = Geom::path_from_piecewise(pwd2, 0.01)[0];
//fuk this
with_direction = Outline::doAdvHalfOutline( newPath, -line_width, miter_lim, extrapolate );
- against_direction = Outline::doAdvHalfOutline( newPath.reverse(), -line_width, miter_lim, extrapolate );
-
+ against_direction = Outline::doAdvHalfOutline( newPath.reverse(), -line_width, miter_lim, extrapolate );
+
/*if (dynamic_cast<const Geom::BezierCurveN<1u> *>(&newPath[newPath.size()])) {
//delete the 'Z'
newPath.erase_last();
@@ -497,54 +492,54 @@ Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, newPath.erase_last();
newPath.append(path_in[i][path_in[i].size() - 1]);
newPath.appendNew<Geom::LineSegment>(newPath.initialPoint());
- newPath.erase_last();
+ newPath.erase_last();
}*/
}
Geom::PathBuilder pb;
-
+
//add in the...do I really need to say this?
pb.moveTo(with_direction.initialPoint());
pb.append(with_direction);
-
+
//add in our line caps
if (!path_in[i].closed()) {
switch (butt) {
- case butt_straight:
- pb.lineTo(against_direction.initialPoint());
- break;
- case butt_round:
- pb.arcTo((-line_width) / 2, (-line_width) / 2, 0., true, true, against_direction.initialPoint() );
- break;
- case butt_pointy:
- //I have ZERO idea what to do here.
- pb.lineTo(against_direction.initialPoint());
- break;
- case butt_square:
- pb.lineTo(against_direction.initialPoint());
- break;
+ case butt_straight:
+ pb.lineTo(against_direction.initialPoint());
+ break;
+ case butt_round:
+ pb.arcTo((-line_width) / 2, (-line_width) / 2, 0., true, true, against_direction.initialPoint() );
+ break;
+ case butt_pointy:
+ //I have ZERO idea what to do here.
+ pb.lineTo(against_direction.initialPoint());
+ break;
+ case butt_square:
+ pb.lineTo(against_direction.initialPoint());
+ break;
}
} else {
pb.moveTo(against_direction.initialPoint());
}
-
+
pb.append(against_direction);
-
+
//cap (if necessary)
if (!path_in[i].closed()) {
switch (butt) {
- case butt_straight:
- pb.lineTo(with_direction.initialPoint());
- break;
- case butt_round:
- pb.arcTo((-line_width) / 2, (-line_width) / 2, 0., true, true, with_direction.initialPoint() );
- break;
- case butt_pointy:
- //I have ZERO idea what to do here.
- pb.lineTo(with_direction.initialPoint());
- break;
- case butt_square:
- pb.lineTo(with_direction.initialPoint());
- break;
+ case butt_straight:
+ pb.lineTo(with_direction.initialPoint());
+ break;
+ case butt_round:
+ pb.arcTo((-line_width) / 2, (-line_width) / 2, 0., true, true, with_direction.initialPoint() );
+ break;
+ case butt_pointy:
+ //I have ZERO idea what to do here.
+ pb.lineTo(with_direction.initialPoint());
+ break;
+ case butt_square:
+ pb.lineTo(with_direction.initialPoint());
+ break;
}
}
pb.flush();
@@ -554,7 +549,7 @@ Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, } else {
Path p = Path();
Path outlinepath = Path();
-
+
p.LoadPath(path_in[i], Geom::Affine(), false, false);
p.Outline(&outlinepath, line_width / 2, static_cast<join_typ>(join), butt, miter_lim);
Geom::PathVector *pv_p = outlinepath.MakePathVector();
diff --git a/src/live_effects/pathoutlineprovider.h b/src/live_effects/pathoutlineprovider.h index 23cc7e2c4..27bc62d45 100644 --- a/src/live_effects/pathoutlineprovider.h +++ b/src/live_effects/pathoutlineprovider.h @@ -12,15 +12,15 @@ enum LineJoinType { LINEJOIN_EXTRAPOLATED }; -namespace Outline +namespace Outline { - unsigned bezierOrder (const Geom::Curve* curve_in); - std::vector<Geom::Path> PathVectorOutline(std::vector<Geom::Path> const & path_in, double line_width, ButtType linecap_type, - LineJoinType linejoin_type, double miter_limit); - - Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, LineJoinType join, - ButtType butt, double miter_lim, bool extrapolate = false); - Geom::Path PathOutsideOutline(Geom::Path const & path_in, double line_width, LineJoinType linejoin_type, double miter_limit); + unsigned bezierOrder (const Geom::Curve* curve_in); + std::vector<Geom::Path> PathVectorOutline(std::vector<Geom::Path> const & path_in, double line_width, ButtType linecap_type, + LineJoinType linejoin_type, double miter_limit); + + /*Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, LineJoinType join, + ButtType butt, double miter_lim, bool extrapolate = false);*/ + Geom::Path PathOutsideOutline(Geom::Path const & path_in, double line_width, LineJoinType linejoin_type, double miter_limit); } #endif // _SEEN_PATH_OUTLINE_H |
