summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJohan B. C. Engelen <jbc.engelen@swissonline.ch>2012-04-14 15:22:15 +0000
committerJohan B. C. Engelen <j.b.c.engelen@alumnus.utwente.nl>2012-04-14 15:22:15 +0000
commit10cd24ae4da25d86677622f847e6962cecf718d0 (patch)
treeca7150c7a61a006384e32cb53e593ce989009844 /src
parentexport dialog: type fix (diff)
downloadinkscape-10cd24ae4da25d86677622f847e6962cecf718d0.tar.gz
inkscape-10cd24ae4da25d86677622f847e6962cecf718d0.zip
powerstroke: more robust method of determining parameters at joins. should fix some bugs. (may introduce new ones...)
(bzr r11247)
Diffstat (limited to 'src')
-rw-r--r--src/live_effects/lpe-powerstroke.cpp89
1 files changed, 18 insertions, 71 deletions
diff --git a/src/live_effects/lpe-powerstroke.cpp b/src/live_effects/lpe-powerstroke.cpp
index 281376cde..a9cf22f6a 100644
--- a/src/live_effects/lpe-powerstroke.cpp
+++ b/src/live_effects/lpe-powerstroke.cpp
@@ -205,47 +205,8 @@ static bool compare_offsets (Geom::Point first, Geom::Point second)
return first[Geom::X] < second[Geom::X];
}
-// find discontinuities in input path
-struct discontinuity_data {
- Geom::Point der0; // unit derivative of 'left' side of join
- Geom::Point der1; // unit derivative of 'right' side of join
- double width; // intended stroke width at join
-};
-std::vector<discontinuity_data> find_discontinuities( Geom::Piecewise<Geom::D2<Geom::SBasis> > const & der,
- Geom::Piecewise<Geom::SBasis> const & x,
- Geom::Piecewise<Geom::SBasis> const & y,
- double eps=Geom::EPSILON )
-{
- std::vector<discontinuity_data> vect;
- for(unsigned i = 1; i < der.size(); i++) {
- if ( ! are_near(der[i-1].at1(), der[i].at0(), eps) ) {
- discontinuity_data data;
-
- data.der0 = der[i-1].at1();
- data.der1 = der[i].at0();
- if ( Geom::are_near(data.der0.length(), 0) ) {
- data.der0 = -unitTangentAt(reverse(der[i-1]),0.,2); // == unitTangentAt(der[i-1], 1, 2);
- }
- if ( Geom::are_near(data.der1.length(), 0) ) {
- data.der1 = unitTangentAt(der[i], 0, 2);
- }
-
- double t = der.cuts[i];
- std::vector< double > rts = roots (x - t); /// @todo this has multiple solutions for general strokewidth paths (generated by spiro interpolator...), ignore for now
- if (!rts.empty()) {
- data.width = y(rts.front());
- } else {
- data.width = 1;
- }
- vect.push_back(data);
- }
- }
- return vect;
-}
-
-
Geom::Path path_from_piecewise_fix_cusps( Geom::Piecewise<Geom::D2<Geom::SBasis> > const & B,
- std::vector<discontinuity_data> const & cusps,
+ Geom::Piecewise<Geom::SBasis> const & y, // width path
LineJoinType jointype,
double miter_limit,
bool forward_direction,
@@ -258,9 +219,6 @@ Geom::Path path_from_piecewise_fix_cusps( Geom::Piecewise<Geom::D2<Geom::SBasis>
return pb.peek().front();
}
- double sign = forward_direction ? 1. : -1.;
-
- unsigned int cusp_i = forward_direction ? 0 : cusps.size()-1;
Geom::Point start = B[0].at0();
pb.moveTo(start);
build_from_sbasis(pb, B[0], tol, false);
@@ -273,9 +231,12 @@ Geom::Path path_from_piecewise_fix_cusps( Geom::Piecewise<Geom::D2<Geom::SBasis>
}
if (!are_near(B[prev_i].at1(), B[i].at0(), tol) )
{ // discontinuity found, so fix it :-)
- discontinuity_data cusp = cusps[cusp_i];
+ double width = y( B.cuts[i] );
- bool on_outside = ( sign*cusp.width*angle_between(cusp.der0, cusp.der1) < 0. );
+ Geom::Point tang1 = -unitTangentAt(reverse(B[prev_i]),0.); // = unitTangentAt(B[prev_i],1);
+ Geom::Point tang2 = unitTangentAt(B[i],0);
+ Geom::Point discontinuity_vec = B[i].at0() - B[prev_i].at1();
+ bool on_outside = ( dot(tang1, discontinuity_vec) >= 0. );
switch (jointype) {
case LINEJOIN_ROUND: {
@@ -289,8 +250,6 @@ Geom::Path path_from_piecewise_fix_cusps( Geom::Piecewise<Geom::D2<Geom::SBasis>
A 2Geom method was created to do exactly this :)
*/
- Geom::Point tang1 = -unitTangentAt(reverse(B[prev_i]),0.); // = unitTangentAt(B[prev_i],1);
- Geom::Point tang2 = unitTangentAt(B[i],0);
boost::optional<Geom::Point> O = intersection_point( B[prev_i].at1(), tang1,
B[i].at0(), tang2 );
if (!O) {
@@ -301,7 +260,7 @@ Geom::Path path_from_piecewise_fix_cusps( Geom::Piecewise<Geom::D2<Geom::SBasis>
Geom::Ellipse ellipse = find_ellipse(B[prev_i].at1(), B[i].at0(), *O);
pb.arcTo( ellipse.ray(Geom::X), ellipse.ray(Geom::Y), ellipse.rot_angle(),
- false, cusp.width < 0, B[i].at0() );
+ false, width < 0, B[i].at0() );
} else {
// we are on the inside, do a simple bevel to connect the paths
pb.lineTo(B[i].at0()); // default to bevel for too shallow cusp angles
@@ -311,8 +270,7 @@ Geom::Path path_from_piecewise_fix_cusps( Geom::Piecewise<Geom::D2<Geom::SBasis>
/* case LINEJOIN_NONE: {
if ( on_outside ) {
// we are on the outside
- Geom::Point der1 = -unitTangentAt(reverse(B[prev_i]),0.); // = unitTangentAt(B[prev_i],1);
- Geom::Point point_on_path = B[prev_i].at1() - rot90(der1) * cusp.width;
+ Geom::Point point_on_path = B[prev_i].at1() - rot90(tang1) * width;
pb.lineTo(point_on_path);
pb.lineTo(B[i].at0());
} else {
@@ -324,13 +282,10 @@ Geom::Path path_from_piecewise_fix_cusps( Geom::Piecewise<Geom::D2<Geom::SBasis>
if (on_outside) {
// we are on the outside, do something complicated to make it look good ;)
- Geom::Point der1 = -unitTangentAt(reverse(B[prev_i]),0.); // = unitTangentAt(B[prev_i],1);
- Geom::Point der2 = unitTangentAt(B[i],0);
-
- Geom::D2<Geom::SBasis> newcurve1 = B[prev_i] * Geom::reflection(rot90(der1), B[prev_i].at1());
+ Geom::D2<Geom::SBasis> newcurve1 = B[prev_i] * Geom::reflection(rot90(tang1), B[prev_i].at1());
Geom::CubicBezier bzr1 = sbasis_to_cubicbezier( reverse(newcurve1) );
- Geom::D2<Geom::SBasis> newcurve2 = B[i] * Geom::reflection(rot90(der2), B[i].at0());
+ Geom::D2<Geom::SBasis> newcurve2 = B[i] * Geom::reflection(rot90(tang2), B[i].at0());
Geom::CubicBezier bzr2 = sbasis_to_cubicbezier( reverse(newcurve2) );
Geom::Crossings cross = crossings(bzr1, bzr2);
@@ -339,9 +294,9 @@ Geom::Path path_from_piecewise_fix_cusps( Geom::Piecewise<Geom::D2<Geom::SBasis>
pb.lineTo(B[i].at0());
} else {
// check size of miter
- Geom::Point point_on_path = B[prev_i].at1() - rot90(der1) * cusp.width;
+ Geom::Point point_on_path = B[prev_i].at1() - rot90(tang1) * width;
Geom::Coord len = distance(bzr1.pointAt(cross[0].ta), point_on_path);
- if (len > fabs(cusp.width) * miter_limit) {
+ if (len > fabs(width) * miter_limit) {
// miter too big: default to bevel
pb.lineTo(B[i].at0());
} else {
@@ -362,15 +317,13 @@ Geom::Path path_from_piecewise_fix_cusps( Geom::Piecewise<Geom::D2<Geom::SBasis>
if (on_outside) {
// we are on the outside, do something complicated to make it look good ;)
- Geom::Point der1 = -unitTangentAt(reverse(B[prev_i]),0.); // = unitTangentAt(B[prev_i],1);
- Geom::Point der2 = unitTangentAt(B[i],0);
- boost::optional<Geom::Point> p = intersection_point( B[prev_i].at1(), der1,
- B[i].at0(), der2 );
+ boost::optional<Geom::Point> p = intersection_point( B[prev_i].at1(), tang1,
+ B[i].at0(), tang2 );
if (p) {
// check size of miter
- Geom::Point point_on_path = B[prev_i].at1() - rot90(der1) * cusp.width;
+ Geom::Point point_on_path = B[prev_i].at1() - rot90(tang1) * width;
Geom::Coord len = distance(*p, point_on_path);
- if (len <= fabs(cusp.width) * miter_limit) {
+ if (len <= fabs(width) * miter_limit) {
// miter OK
pb.lineTo(*p);
}
@@ -384,9 +337,6 @@ Geom::Path path_from_piecewise_fix_cusps( Geom::Piecewise<Geom::D2<Geom::SBasis>
}
case LINEJOIN_SPIRO: {
if (on_outside) {
- Geom::Point tang1 = -unitTangentAt(reverse(B[prev_i]),0.); // = unitTangentAt(B[prev_i],1);
- Geom::Point tang2 = unitTangentAt(B[i],0);
-
Geom::Point direction = B[i].at0() - B[prev_i].at1();
double tang1_sign = dot(direction,tang1);
double tang2_sign = dot(direction,tang2);
@@ -419,8 +369,6 @@ Geom::Path path_from_piecewise_fix_cusps( Geom::Piecewise<Geom::D2<Geom::SBasis>
pb.lineTo(B[i].at0());
break;
}
-
- cusp_i += forward_direction ? 1 : -1;
}
build_from_sbasis(pb, B[i], tol, false);
prev_i = i;
@@ -491,14 +439,13 @@ LPEPowerStroke::doEffect_path (std::vector<Geom::Path> const & path_in)
y = portion(y, rtsmin.at(0), rtsmax.at(0));
}
- std::vector<discontinuity_data> cusps = find_discontinuities(der, x, y);
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, cusps, jointype, miter_limit, true, LPE_CONVERSION_TOLERANCE);
- Geom::Path fixed_mirrorpath = path_from_piecewise_fix_cusps( mirrorpath, cusps, jointype, miter_limit, false, LPE_CONVERSION_TOLERANCE);
+ 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 (path_in[0].closed()) {
fixed_path.close(true);