summaryrefslogtreecommitdiffstats
path: root/src/live_effects/lpe-patternalongpath.cpp
diff options
context:
space:
mode:
authorTed Gould <ted@gould.cx>2008-11-21 05:24:08 +0000
committerTed Gould <ted@canonical.com>2008-11-21 05:24:08 +0000
commit44a3a78fb6a3863c0c7f3c1193837337e68a67e4 (patch)
tree1722ee5ec6f88c881cd4124923354b3c1311501b /src/live_effects/lpe-patternalongpath.cpp
parentMerge from trunk (diff)
downloadinkscape-44a3a78fb6a3863c0c7f3c1193837337e68a67e4.tar.gz
inkscape-44a3a78fb6a3863c0c7f3c1193837337e68a67e4.zip
Merge from fe-moved
(bzr r6891)
Diffstat (limited to 'src/live_effects/lpe-patternalongpath.cpp')
-rw-r--r--src/live_effects/lpe-patternalongpath.cpp195
1 files changed, 107 insertions, 88 deletions
diff --git a/src/live_effects/lpe-patternalongpath.cpp b/src/live_effects/lpe-patternalongpath.cpp
index 0e5011e51..954a01029 100644
--- a/src/live_effects/lpe-patternalongpath.cpp
+++ b/src/live_effects/lpe-patternalongpath.cpp
@@ -66,7 +66,8 @@ LPEPatternAlongPath::LPEPatternAlongPath(LivePathEffectObject *lpeobject) :
normal_offset(_("Normal offset"), "", "normal_offset", &wr, this, 0),
tang_offset(_("Tangential offset"), "", "tang_offset", &wr, this, 0),
prop_units(_("Offsets in unit of pattern size"), _("Spacing, tangential and normal offset are expressed as a ratio of width/height"), "prop_units", &wr, this, false),
- vertical_pattern(_("Pattern is vertical"), _("Rotate pattern 90 deg before applying"), "vertical_pattern", &wr, this, false)
+ vertical_pattern(_("Pattern is vertical"), _("Rotate pattern 90 deg before applying"), "vertical_pattern", &wr, this, false),
+ fuse_tolerance(_("Fuse nearby ends"), "Fuse ends closer than this number. 0 means don't fuse.", "fuse_tolerance", &wr, this, 0)
{
registerParameter( dynamic_cast<Parameter *>(&pattern) );
registerParameter( dynamic_cast<Parameter *>(&copytype) );
@@ -77,6 +78,7 @@ LPEPatternAlongPath::LPEPatternAlongPath(LivePathEffectObject *lpeobject) :
registerParameter( dynamic_cast<Parameter *>(&tang_offset) );
registerParameter( dynamic_cast<Parameter *>(&prop_units) );
registerParameter( dynamic_cast<Parameter *>(&vertical_pattern) );
+ registerParameter( dynamic_cast<Parameter *>(&fuse_tolerance) );
prop_scale.param_set_digits(3);
prop_scale.param_set_increments(0.01, 0.10);
@@ -94,105 +96,122 @@ LPEPatternAlongPath::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > con
/* 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;
PAPCopyType type = copytype.get_value();
D2<Piecewise<SBasis> > patternd2 = make_cuts_independent(pattern.get_pwd2());
Piecewise<SBasis> x0 = vertical_pattern.get_value() ? Piecewise<SBasis>(patternd2[1]) : Piecewise<SBasis>(patternd2[0]);
Piecewise<SBasis> y0 = vertical_pattern.get_value() ? Piecewise<SBasis>(patternd2[0]) : Piecewise<SBasis>(patternd2[1]);
- Interval pattBndsX = bounds_exact(x0);
- x0 -= pattBndsX.min();
- Interval pattBndsY = bounds_exact(y0);
- y0 -= pattBndsY.middle();
-
- double xspace = spacing;
- double noffset = normal_offset;
- double toffset = tang_offset;
- if (prop_units.get_value()){
- xspace *= pattBndsX.extent();
- noffset *= pattBndsY.extent();
- toffset *= pattBndsX.extent();
- }
+ OptInterval pattBndsX = bounds_exact(x0);
+ OptInterval pattBndsY = bounds_exact(y0);
+ if (pattBndsX && pattBndsY) {
+ x0 -= pattBndsX->min();
+ y0 -= pattBndsY->middle();
+
+ double xspace = spacing;
+ double noffset = normal_offset;
+ double toffset = tang_offset;
+ if (prop_units.get_value() && pattBndsY){
+ xspace *= pattBndsX->extent();
+ noffset *= pattBndsY->extent();
+ toffset *= pattBndsX->extent();
+ }
- //Prevent more than 90% overlap...
- if (xspace < -pattBndsX.extent()*.9) {
- xspace = -pattBndsX.extent()*.9;
- }
- //TODO: dynamical update of parameter ranges?
- //if (prop_units.get_value()){
- // spacing.param_set_range(-.9, NR_HUGE);
- // }else{
- // spacing.param_set_range(-pattBndsX.extent()*.9, NR_HUGE);
- // }
-
- y0+=noffset;
-
- 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++){
- Geom::Piecewise<Geom::D2<Geom::SBasis> > path_i = paths_in[idx];
- Piecewise<SBasis> x = x0;
- Piecewise<SBasis> y = y0;
- Piecewise<D2<SBasis> > uskeleton = arc_length_parametrization(path_i,2,.1);
- 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;
- switch(type) {
- case PAPCT_REPEATED:
- nbCopies = static_cast<int>(floor((uskeleton.domain().extent() - toffset + xspace)/(pattBndsX.extent()+xspace)));
- pattBndsX = Interval(pattBndsX.min(),pattBndsX.max()+xspace);
- break;
-
- case PAPCT_SINGLE:
- nbCopies = (toffset + pattBndsX.extent() < uskeleton.domain().extent()) ? 1 : 0;
- break;
-
- case PAPCT_SINGLE_STRETCHED:
- nbCopies = 1;
- scaling = (uskeleton.domain().extent() - toffset)/pattBndsX.extent();
- break;
-
- case PAPCT_REPEATED_STRETCHED:
- // if uskeleton is closed:
- if(path_i.segs.front().at0() == path_i.segs.back().at1()){
- nbCopies = static_cast<int>(std::floor((uskeleton.domain().extent() - toffset)/(pattBndsX.extent()+xspace)));
- pattBndsX = Interval(pattBndsX.min(),pattBndsX.max()+xspace);
- scaling = (uskeleton.domain().extent() - toffset)/(((double)nbCopies)*pattBndsX.extent());
- // if not closed: no space at the end
+ //Prevent more than 90% overlap...
+ if (xspace < -pattBndsX->extent()*.9) {
+ xspace = -pattBndsX->extent()*.9;
+ }
+ //TODO: dynamical update of parameter ranges?
+ //if (prop_units.get_value()){
+ // spacing.param_set_range(-.9, NR_HUGE);
+ // }else{
+ // spacing.param_set_range(-pattBndsX.extent()*.9, NR_HUGE);
+ // }
+
+ y0+=noffset;
+
+ 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++){
+ Geom::Piecewise<Geom::D2<Geom::SBasis> > path_i = paths_in[idx];
+ Piecewise<SBasis> x = x0;
+ Piecewise<SBasis> y = y0;
+ Piecewise<D2<SBasis> > uskeleton = arc_length_parametrization(path_i,2,.1);
+ 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;
+ switch(type) {
+ case PAPCT_REPEATED:
+ nbCopies = static_cast<int>(floor((uskeleton.domain().extent() - toffset + xspace)/(pattBndsX->extent()+xspace)));
+ pattBndsX = Interval(pattBndsX->min(),pattBndsX->max()+xspace);
+ break;
+
+ case PAPCT_SINGLE:
+ nbCopies = (toffset + pattBndsX->extent() < uskeleton.domain().extent()) ? 1 : 0;
+ break;
+
+ case PAPCT_SINGLE_STRETCHED:
+ nbCopies = 1;
+ scaling = (uskeleton.domain().extent() - toffset)/pattBndsX->extent();
+ break;
+
+ case PAPCT_REPEATED_STRETCHED:
+ // if uskeleton is closed:
+ if(path_i.segs.front().at0() == path_i.segs.back().at1()){
+ nbCopies = static_cast<int>(std::floor((uskeleton.domain().extent() - toffset)/(pattBndsX->extent()+xspace)));
+ pattBndsX = Interval(pattBndsX->min(),pattBndsX->max()+xspace);
+ scaling = (uskeleton.domain().extent() - toffset)/(((double)nbCopies)*pattBndsX->extent());
+ // if not closed: no space at the end
+ }else{
+ nbCopies = static_cast<int>(std::floor((uskeleton.domain().extent() - toffset + xspace)/(pattBndsX->extent()+xspace)));
+ pattBndsX = Interval(pattBndsX->min(),pattBndsX->max()+xspace);
+ scaling = (uskeleton.domain().extent() - toffset)/(((double)nbCopies)*pattBndsX->extent() - xspace);
+ }
+ break;
+
+ default:
+ return pwd2_in;
+ };
+
+ double pattWidth = pattBndsX->extent() * scaling;
+
+ if (scaling != 1.0) {
+ x*=scaling;
+ }
+ if ( scale_y_rel.get_value() ) {
+ y*=(scaling*prop_scale);
+ } else {
+ if (prop_scale != 1.0) y *= prop_scale;
+ }
+ x += toffset;
+
+ double offs = 0;
+ for (int i=0; i<nbCopies; i++){
+ if (fuse_tolerance > 0){
+ 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{
- nbCopies = static_cast<int>(std::floor((uskeleton.domain().extent() - toffset + xspace)/(pattBndsX.extent()+xspace)));
- pattBndsX = Interval(pattBndsX.min(),pattBndsX.max()+xspace);
- scaling = (uskeleton.domain().extent() - toffset)/(((double)nbCopies)*pattBndsX.extent() - xspace);
+ output.concat(compose(uskeleton,x+offs)+y*compose(n,x+offs));
}
- break;
-
- default:
- return pwd2_in;
- };
-
- double pattWidth = pattBndsX.extent() * scaling;
-
- if (scaling != 1.0) {
- x*=scaling;
- }
- if ( scale_y_rel.get_value() ) {
- y*=(scaling*prop_scale);
- } else {
- if (prop_scale != 1.0) y *= prop_scale;
+ offs+=pattWidth;
+ }
}
- x += toffset;
-
- double offs = 0;
- for (int i=0; i<nbCopies; i++){
- output.concat(compose(uskeleton,x+offs)+y*compose(n,x+offs));
- offs+=pattWidth;
+ if (fuse_tolerance > 0){
+ pre_output = fuse_nearby_ends(pre_output, fuse_tolerance);
+ for (unsigned i=0; i<pre_output.size(); i++){
+ output.concat(pre_output[i]);
+ }
}
+ return output;
+ } else {
+ return pwd2_in;
}
- return output;
}
LPEFreehandShape::LPEFreehandShape(LivePathEffectObject *lpeobject) : LPEPatternAlongPath(lpeobject)