diff options
| author | Jabier Arraiza Cenoz <jabier.arraiza@marker.es> | 2014-11-13 17:04:22 +0000 |
|---|---|---|
| committer | Jabiertxof <jtx@jtx.marker.es> | 2014-11-13 17:04:22 +0000 |
| commit | 165025d5aa43570d3905d312632199efddd45c9a (patch) | |
| tree | 41cb1a192ecac0a4f4ee6e24af28f503ca0617d7 /src | |
| parent | update to trunk (diff) | |
| download | inkscape-165025d5aa43570d3905d312632199efddd45c9a.tar.gz inkscape-165025d5aa43570d3905d312632199efddd45c9a.zip | |
Fixed bugs pointed by su_v.
Added inverse option to merges
(bzr r13682.1.6)
Diffstat (limited to 'src')
| -rw-r--r-- | src/live_effects/lpe-mirror_symmetry.cpp | 125 | ||||
| -rw-r--r-- | src/live_effects/lpe-mirror_symmetry.h | 6 | ||||
| -rw-r--r-- | src/selection-chemistry.cpp | 2 |
3 files changed, 85 insertions, 48 deletions
diff --git a/src/live_effects/lpe-mirror_symmetry.cpp b/src/live_effects/lpe-mirror_symmetry.cpp index fa588fe96..c21c65a3e 100644 --- a/src/live_effects/lpe-mirror_symmetry.cpp +++ b/src/live_effects/lpe-mirror_symmetry.cpp @@ -19,7 +19,7 @@ #include <sp-path.h> #include <display/curve.h> #include <svg/path-string.h> - +#include "helper/geom.h" #include <2geom/path.h> #include <2geom/path-intersection.h> #include <2geom/transforms.h> @@ -31,13 +31,15 @@ namespace LivePathEffect { LPEMirrorSymmetry::LPEMirrorSymmetry(LivePathEffectObject *lpeobject) : Effect(lpeobject), discard_orig_path(_("Discard original path?"), _("Check this to only keep the mirrored part of the path"), "discard_orig_path", &wr, this, false), - joinPaths(_("Join the paths"), _("Join the resulting paths"), "joinPaths", &wr, this, true), + fusionPaths(_("Fusioned symetry"), _("Fusion right side whith symm"), "fusionPaths", &wr, this, true), + reverseFusion(_("Reverse fusion"), _("Reverse fusion"), "reverseFusion", &wr, this, false), reflection_line(_("Reflection line:"), _("Line which serves as 'mirror' for the reflection"), "reflection_line", &wr, this, "M0,0 L1,0") { show_orig_path = true; registerParameter( dynamic_cast<Parameter *>(&discard_orig_path) ); - registerParameter( dynamic_cast<Parameter *>(&joinPaths) ); + registerParameter( dynamic_cast<Parameter *>(&fusionPaths) ); + registerParameter( dynamic_cast<Parameter *>(&reverseFusion) ); registerParameter( dynamic_cast<Parameter *>(&reflection_line) ); } @@ -49,6 +51,8 @@ void LPEMirrorSymmetry::doBeforeEffect (SPLPEItem const* lpeitem) { SPLPEItem * item = const_cast<SPLPEItem*>(lpeitem); + std::vector<Geom::Path> mline(reflection_line.get_pathvector()); + lineSeparation.setPoints(mline[0].initialPoint(),mline[0].finalPoint()); item->apply_to_clippath(item); item->apply_to_mask(item); } @@ -66,6 +70,14 @@ LPEMirrorSymmetry::doOnApply (SPLPEItem const* lpeitem) reflection_line.set_new_value(rline, true); } +int +LPEMirrorSymmetry::pointSideOfLine(Geom::Point A, Geom::Point B, Geom::Point X) +{ + //http://stackoverflow.com/questions/1560492/how-to-tell-whether-a-point-is-to-the-right-or-left-side-of-a-line + double pos = (B[Geom::X]-A[Geom::X])*(X[Geom::Y]-A[Geom::Y]) - (B[Geom::Y]-A[Geom::Y])*(X[Geom::X]-A[Geom::X]); + return (pos < 0) ? -1 : (pos > 0); +} + std::vector<Geom::Path> LPEMirrorSymmetry::doEffect_path (std::vector<Geom::Path> const & path_in) { @@ -73,16 +85,20 @@ LPEMirrorSymmetry::doEffect_path (std::vector<Geom::Path> const & path_in) if ( reflection_line.get_pathvector().empty() ) { return path_in; } - + Geom::PathVector const original_pathv = pathv_to_linear_and_cubic_beziers(path_in); std::vector<Geom::Path> path_out; - std::vector<Geom::Path> mline(reflection_line.get_pathvector()); + Geom::Path mlineExpanded; + Geom::Point lineStart = lineSeparation.pointAt(-100000.0); + Geom::Point lineEnd = lineSeparation.pointAt(100000.0); + mlineExpanded.start( lineStart); + mlineExpanded.appendNew<Geom::LineSegment>( lineEnd); - if (!discard_orig_path && !joinPaths) { + if (!discard_orig_path && !fusionPaths) { path_out = path_in; } - Geom::Point A(mline.front().initialPoint()); - Geom::Point B(mline.back().finalPoint()); + Geom::Point A(lineStart); + Geom::Point B(lineEnd); Geom::Affine m1(1.0, 0.0, 0.0, 1.0, A[0], A[1]); double hyp = Geom::distance(A, B); @@ -97,65 +113,82 @@ LPEMirrorSymmetry::doEffect_path (std::vector<Geom::Path> const & path_in) m = m * m2.inverse(); m = m * m1; - if(joinPaths && !discard_orig_path){ - for (Geom::PathVector::const_iterator path_it = path_in.begin(); - path_it != path_in.end(); ++path_it) { + if(fusionPaths && !discard_orig_path){ + for (Geom::PathVector::const_iterator path_it = original_pathv.begin(); + path_it != original_pathv.end(); ++path_it) { if (path_it->empty()){ continue; } - Geom::Path original; - Geom::Path mlineExpanded; - Geom::Line lineSeparation; - lineSeparation.setPoints(mline[0].initialPoint(),mline[0].finalPoint()); - Geom::Point lineStart = lineSeparation.pointAt(-100000.0); - Geom::Point lineEnd = lineSeparation.pointAt(100000.0); - mlineExpanded.start( lineStart); - mlineExpanded.appendNew<Geom::LineSegment>( lineEnd); - Geom::Crossings cs = crossings(*path_it, mlineExpanded); double timeStart = 0.0; - //http://stackoverflow.com/questions/1560492/how-to-tell-whether-a-point-is-to-the-right-or-left-side-of-a-line - double pos = (lineEnd[Geom::X]-lineStart[Geom::X])*(path_it->initialPoint()[Geom::Y]-lineStart[Geom::Y]) - (lineEnd[Geom::Y]-lineStart[Geom::Y])*(path_it->initialPoint()[Geom::X]-lineStart[Geom::X]); - int position = (pos < 0) ? -1 : (pos > 0); - unsigned int counter = 0; - + int position = 0; + bool end_open = false; + if (path_it->closed()) { + const Geom::Curve &closingline = path_it->back_closed(); + if (!are_near(closingline.initialPoint(), closingline.finalPoint())) { + end_open = true; + } + } + Geom::Path original = (Geom::Path)(*path_it); + if(end_open && path_it->closed()){ + original.close(false); + original.appendNew<Geom::LineSegment>( original.initialPoint() ); + original.close(true); + } + Geom::Crossings cs = crossings(original, mlineExpanded); for(unsigned int i = 0; i < cs.size(); i++) { double timeEnd = cs[i].ta; - Geom::Path portion = path_it->portion(timeStart, timeEnd); - if(position == -1 && i==0){ - counter++; + Geom::Path portion = original.portion(timeStart, timeEnd); + Geom::Point middle = portion.pointAt((double)portion.size()/2.0); + position = pointSideOfLine(lineStart, lineEnd, middle); + if(reverseFusion){ + position *= -1; } - if(counter%2!=0){ - original = portion; - original.append(portion.reverse() * m, (Geom::Path::Stitching)1); + if(position == -1){ + Geom::Path mirror = portion.reverse() * m; + mirror.setInitial(portion.finalPoint()); + portion.append(mirror); if(i!=0){ - original.close(); + portion.setFinal(portion.initialPoint()); + portion.close(); } - path_out.push_back(original); - original.clear(); + path_out.push_back(portion); } + portion.clear(); timeStart = timeEnd; - counter++; } - if(cs.size()!=0 && ((cs.size()%2 == 0 && position == -1)||(cs.size()%2 != 0 && position == 1))){ - Geom::Path portion = path_it->portion(timeStart, nearest_point(path_it->finalPoint(), *path_it)); - original = portion.reverse(); - original.append(portion * m, (Geom::Path::Stitching)1); - if (!path_it->closed()){ - path_out.push_back(original); + position = pointSideOfLine(lineStart, lineEnd, original.finalPoint()); + if(reverseFusion){ + position *= -1; + } + if(cs.size()!=0 && position == -1){ + Geom::Path portion = original.portion(timeStart, original.size()); + portion = portion.reverse(); + Geom::Path mirror = portion.reverse() * m; + mirror.setInitial(portion.finalPoint()); + portion.append(mirror); + portion = portion.reverse(); + if (!original.closed()){ + path_out.push_back(portion); } else { - path_out[0].append(original.reverse(), (Geom::Path::Stitching)1); + if(cs.size() >1 ){ + portion.setFinal(path_out[0].initialPoint()); + portion.setInitial(path_out[0].finalPoint()); + path_out[0].append(portion); + } else { + path_out.push_back(portion); + } path_out[0].close(); } - original.clear(); + portion.clear(); } if(cs.size() == 0 && position == -1){ - path_out.push_back(*path_it); - path_out.push_back(*path_it * m); + path_out.push_back(original); + path_out.push_back(original * m); } } } - if (!joinPaths) { + if (!fusionPaths || discard_orig_path) { for (int i = 0; i < static_cast<int>(path_in.size()); ++i) { path_out.push_back(path_in[i] * m); } diff --git a/src/live_effects/lpe-mirror_symmetry.h b/src/live_effects/lpe-mirror_symmetry.h index 2ea8161d4..c925f220f 100644 --- a/src/live_effects/lpe-mirror_symmetry.h +++ b/src/live_effects/lpe-mirror_symmetry.h @@ -34,12 +34,16 @@ public: virtual void doBeforeEffect (SPLPEItem const* lpeitem); + virtual int pointSideOfLine(Geom::Point A, Geom::Point B, Geom::Point X); + virtual std::vector<Geom::Path> doEffect_path (std::vector<Geom::Path> const & path_in); private: BoolParam discard_orig_path; - BoolParam joinPaths; + BoolParam fusionPaths; + BoolParam reverseFusion; PathParam reflection_line; + Geom::Line lineSeparation; LPEMirrorSymmetry(const LPEMirrorSymmetry&); LPEMirrorSymmetry& operator=(const LPEMirrorSymmetry&); diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp index d0ef0afea..d00e8d702 100644 --- a/src/selection-chemistry.cpp +++ b/src/selection-chemistry.cpp @@ -4186,7 +4186,7 @@ void sp_selection_unset_mask(SPDesktop *desktop, bool apply_clip_path) { for ( SPObject *child = obj->firstChild() ; child; child = child->getNext() ) { // Collect all clipped paths and masks within a single group Inkscape::XML::Node *copy = SP_OBJECT(child)->getRepr()->duplicate(xml_doc); - if(copy->attribute("inkscape:original-d")) + if(copy->attribute("inkscape:original-d") && copy->attribute("inkscape:path-effect")) { copy->setAttribute("d", copy->attribute("inkscape:original-d")); } |
