diff options
| author | Tavmjong Bah <tavmjong@free.fr> | 2015-03-27 16:37:16 +0000 |
|---|---|---|
| committer | tavmjong-free <tavmjong@free.fr> | 2015-03-27 16:37:16 +0000 |
| commit | 8c5e33effcd16fac6ff807fa4b1700291892cbf7 (patch) | |
| tree | 41ec1b375ecb5f81f77adfdff72c0a104b8b5c92 /src/helper | |
| parent | Fix a crash on perspective/envelope LPE introduced in recent refactor of poin... (diff) | |
| download | inkscape-8c5e33effcd16fac6ff807fa4b1700291892cbf7.tar.gz inkscape-8c5e33effcd16fac6ff807fa4b1700291892cbf7.zip | |
Fix calculation of miter limit. Implement 'miter-clip' line join.
(bzr r14033)
Diffstat (limited to 'src/helper')
| -rw-r--r-- | src/helper/geom-pathstroke.cpp | 55 | ||||
| -rw-r--r-- | src/helper/geom-pathstroke.h | 3 |
2 files changed, 50 insertions, 8 deletions
diff --git a/src/helper/geom-pathstroke.cpp b/src/helper/geom-pathstroke.cpp index d3147f233..1908f2db7 100644 --- a/src/helper/geom-pathstroke.cpp +++ b/src/helper/geom-pathstroke.cpp @@ -6,6 +6,7 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ +#include <iomanip> #include <2geom/path-sink.h> #include <2geom/point.h> #include <2geom/bezier-curve.h> @@ -150,7 +151,7 @@ void round_join(Geom::Path& res, Geom::Curve const& outgoing, double /*miter*/, res.append(outgoing); } -void miter_join(Geom::Path& res, Geom::Curve const& outgoing, double miter, double width) +void miter_join_internal(Geom::Path& res, Geom::Curve const& outgoing, double miter, double width, bool clip) { Geom::Curve const& incoming = res.back(); Geom::Point tang1 = Geom::unitTangentAt(reverse(incoming.toSBasis()), 0.); @@ -161,8 +162,8 @@ void miter_join(Geom::Path& res, Geom::Curve const& outgoing, double miter, doub if (p.isFinite()) { // check size of miter - Geom::Point point_on_path = incoming.finalPoint() - Geom::rot90(tang1)*width; - satisfied = Geom::distance(p, point_on_path) <= miter; + Geom::Point point_on_path = incoming.finalPoint() + Geom::rot90(tang1)*width; + satisfied = Geom::distance(p, point_on_path) <= miter * 2.0 * width; if (satisfied) { // miter OK, check to see if we can do a relocation bool ls = res.back_open().degreesOfFreedom() <= 4; @@ -171,6 +172,31 @@ void miter_join(Geom::Path& res, Geom::Curve const& outgoing, double miter, doub } else { res.appendNew<Geom::LineSegment>(p); } + } else if (clip) { + // miter needs clipping, find two points + Geom::Line bisector(point_on_path, p); + Geom::Point point_limit = point_on_path + miter * 2.0 * width * bisector.versor(); + + Geom::Line line_limit = + Geom::Line::from_origin_and_versor( point_limit, bisector.versor().cw() ); + + Geom::Line incoming_line( incoming.finalPoint(), p ); + Geom::Line outgoing_line( p, outgoing.initialPoint() ); + + Geom::OptCrossing i1 = intersection( line_limit, incoming_line ); + Geom::OptCrossing i2 = intersection( line_limit, outgoing_line ); + + // It would be nice to have a simple point returned by intersection! + Geom::Point p1 = line_limit.pointAt( (*i1).ta ); + Geom::Point p2 = line_limit.pointAt( (*i2).ta ); + + bool ls = res.back_open().degreesOfFreedom() <= 4; + if (ls) { + res.setFinal(p1); + } else { + res.appendNew<Geom::LineSegment>(p1); + } + res.appendNew<Geom::LineSegment>(p2); } } @@ -179,13 +205,21 @@ void miter_join(Geom::Path& res, Geom::Curve const& outgoing, double miter, doub // check if we can do another relocation bool ls = outgoing.degreesOfFreedom() <= 4; - if (satisfied && ls) { + if ( (satisfied || clip) && ls) { res.setFinal(outgoing.finalPoint()); } else { res.append(outgoing); } } +void miter_join(Geom::Path& res, Geom::Curve const& outgoing, double miter, double width) { + miter_join_internal( res, outgoing, miter, width, false ); +} + +void miter_clip_join(Geom::Path& res, Geom::Curve const& outgoing, double miter, double width) { + miter_join_internal( res, outgoing, miter, width, true ); +} + Geom::Point pick_solution(Geom::Point points[2], Geom::Point tang2, Geom::Point endPt) { Geom::Point sol; @@ -301,9 +335,13 @@ void outline_helper(Geom::Path& res, Geom::Path const& to_add, double width, dou return; } - Geom::Point tang1 = -Geom::unitTangentAt(reverse(res.back().toSBasis()), 0.); - Geom::Point discontinuity_vec = to_add.initialPoint() - res.finalPoint(); - bool on_outside = (Geom::dot(tang1, discontinuity_vec) >= 0); + Geom::Point tang1 = Geom::unitTangentAt(reverse(res.back().toSBasis()), 0.); + Geom::Point tang2 = Geom::unitTangentAt(to_add.front().toSBasis(), 0.); + // Geom::Point discontinuity_vec = to_add.initialPoint() - res.finalPoint(); + bool on_outside = (Geom::cross(tang1, tang2) < 0); + // std::cout << std::fixed << std::setprecision(3) + // << " in: " << tang1 << " out: " << tang2 + // << " side: " << (on_outside?"inside":"outside") << std::endl; if (on_outside) { join_func *jf; @@ -317,6 +355,9 @@ void outline_helper(Geom::Path& res, Geom::Path const& to_add, double width, dou case Inkscape::JOIN_EXTRAPOLATE: jf = &extrapolate_join; break; + case Inkscape::JOIN_MITER_CLIP: + jf = &miter_clip_join; + break; default: jf = &miter_join; } diff --git a/src/helper/geom-pathstroke.h b/src/helper/geom-pathstroke.h index fe79e2777..0cfb9f817 100644 --- a/src/helper/geom-pathstroke.h +++ b/src/helper/geom-pathstroke.h @@ -18,6 +18,7 @@ enum LineJoinType { JOIN_BEVEL, JOIN_ROUND, JOIN_MITER, + JOIN_MITER_CLIP, JOIN_EXTRAPOLATE, }; @@ -34,7 +35,7 @@ enum LineCapType { * * @param input * @param width Amount to offset. - * @param miter Miter limit. Only used with JOIN_EXTRAPOLATE and JOIN_MITER. + * @param miter Miter limit. Only used with JOIN_MITER, JOIN_MITER_CLIP, and JOIN_EXTRAPOLATE. * @param join */ Geom::Path half_outline(Geom::Path const& input, double width, double miter, LineJoinType join = JOIN_BEVEL); |
