summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTavmjong Bah <tavmjong@free.fr>2015-03-27 16:37:16 +0000
committertavmjong-free <tavmjong@free.fr>2015-03-27 16:37:16 +0000
commit8c5e33effcd16fac6ff807fa4b1700291892cbf7 (patch)
tree41ec1b375ecb5f81f77adfdff72c0a104b8b5c92 /src
parentFix a crash on perspective/envelope LPE introduced in recent refactor of poin... (diff)
downloadinkscape-8c5e33effcd16fac6ff807fa4b1700291892cbf7.tar.gz
inkscape-8c5e33effcd16fac6ff807fa4b1700291892cbf7.zip
Fix calculation of miter limit. Implement 'miter-clip' line join.
(bzr r14033)
Diffstat (limited to 'src')
-rw-r--r--src/helper/geom-pathstroke.cpp55
-rw-r--r--src/helper/geom-pathstroke.h3
-rw-r--r--src/live_effects/lpe-jointype.cpp7
3 files changed, 54 insertions, 11 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);
diff --git a/src/live_effects/lpe-jointype.cpp b/src/live_effects/lpe-jointype.cpp
index c7ea64b77..0111a0f99 100644
--- a/src/live_effects/lpe-jointype.cpp
+++ b/src/live_effects/lpe-jointype.cpp
@@ -28,9 +28,10 @@ namespace Inkscape {
namespace LivePathEffect {
static const Util::EnumData<unsigned> JoinTypeData[] = {
- {JOIN_BEVEL, N_("Beveled"), "bevel"},
- {JOIN_ROUND, N_("Rounded"), "round"},
- {JOIN_MITER, N_("Miter"), "miter"},
+ {JOIN_BEVEL, N_("Beveled"), "bevel"},
+ {JOIN_ROUND, N_("Rounded"), "round"},
+ {JOIN_MITER, N_("Miter"), "miter"},
+ {JOIN_MITER_CLIP, N_("Miter Clip"), "miter-clip"},
{JOIN_EXTRAPOLATE, N_("Extrapolated arc"), "extrp_arc"},
};