~centralelyon2010/inkscape/imagelinks2

« back to all changes in this revision

Viewing changes to src/live_effects/lpe-patternalongpath.cpp

  • Committer: Ted Gould
  • Date: 2008-11-21 05:24:08 UTC
  • Revision ID: ted@canonical.com-20081121052408-tilucis2pjrrpzxx
MergeĀ fromĀ fe-moved

Show diffs side-by-side

added added

removed removed

Lines of Context:
66
66
    normal_offset(_("Normal offset"), "", "normal_offset", &wr, this, 0),
67
67
    tang_offset(_("Tangential offset"), "", "tang_offset", &wr, this, 0),
68
68
    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),
69
 
    vertical_pattern(_("Pattern is vertical"), _("Rotate pattern 90 deg before applying"), "vertical_pattern", &wr, this, false)
 
69
    vertical_pattern(_("Pattern is vertical"), _("Rotate pattern 90 deg before applying"), "vertical_pattern", &wr, this, false),
 
70
    fuse_tolerance(_("Fuse nearby ends"), "Fuse ends closer than this number. 0 means don't fuse.", "fuse_tolerance", &wr, this, 0)
70
71
{
71
72
    registerParameter( dynamic_cast<Parameter *>(&pattern) );
72
73
    registerParameter( dynamic_cast<Parameter *>(&copytype) );
77
78
    registerParameter( dynamic_cast<Parameter *>(&tang_offset) );
78
79
    registerParameter( dynamic_cast<Parameter *>(&prop_units) );
79
80
    registerParameter( dynamic_cast<Parameter *>(&vertical_pattern) );
 
81
    registerParameter( dynamic_cast<Parameter *>(&fuse_tolerance) );
80
82
 
81
83
    prop_scale.param_set_digits(3);
82
84
    prop_scale.param_set_increments(0.01, 0.10);
94
96
 
95
97
/* Much credit should go to jfb and mgsloan of lib2geom development for the code below! */
96
98
    Piecewise<D2<SBasis> > output;
 
99
    std::vector<Geom::Piecewise<Geom::D2<Geom::SBasis> > > pre_output;
97
100
 
98
101
    PAPCopyType type = copytype.get_value();
99
102
 
100
103
    D2<Piecewise<SBasis> > patternd2 = make_cuts_independent(pattern.get_pwd2());
101
104
    Piecewise<SBasis> x0 = vertical_pattern.get_value() ? Piecewise<SBasis>(patternd2[1]) : Piecewise<SBasis>(patternd2[0]);
102
105
    Piecewise<SBasis> y0 = vertical_pattern.get_value() ? Piecewise<SBasis>(patternd2[0]) : Piecewise<SBasis>(patternd2[1]);
103
 
    Interval pattBndsX = bounds_exact(x0);
104
 
    x0 -= pattBndsX.min();
105
 
    Interval pattBndsY = bounds_exact(y0);
106
 
    y0 -= pattBndsY.middle();
107
 
 
108
 
    double xspace  = spacing;
109
 
    double noffset = normal_offset;
110
 
    double toffset = tang_offset;
111
 
    if (prop_units.get_value()){
112
 
        xspace  *= pattBndsX.extent();
113
 
        noffset *= pattBndsY.extent();
114
 
        toffset *= pattBndsX.extent();
115
 
    }
116
 
 
117
 
    //Prevent more than 90% overlap...
118
 
    if (xspace < -pattBndsX.extent()*.9) {
119
 
        xspace = -pattBndsX.extent()*.9;
120
 
    }
121
 
    //TODO: dynamical update of parameter ranges?
122
 
    //if (prop_units.get_value()){
123
 
    //        spacing.param_set_range(-.9, NR_HUGE);
124
 
    //    }else{
125
 
    //        spacing.param_set_range(-pattBndsX.extent()*.9, NR_HUGE);
126
 
    //    }
127
 
 
128
 
    y0+=noffset;
129
 
 
130
 
    std::vector<Geom::Piecewise<Geom::D2<Geom::SBasis> > > paths_in;
131
 
    paths_in = split_at_discontinuities(pwd2_in);
132
 
 
133
 
    for (unsigned idx = 0; idx < paths_in.size(); idx++){
134
 
        Geom::Piecewise<Geom::D2<Geom::SBasis> > path_i = paths_in[idx];
135
 
        Piecewise<SBasis> x = x0;
136
 
        Piecewise<SBasis> y = y0;
137
 
        Piecewise<D2<SBasis> > uskeleton = arc_length_parametrization(path_i,2,.1);
138
 
        uskeleton = remove_short_cuts(uskeleton,.01);
139
 
        Piecewise<D2<SBasis> > n = rot90(derivative(uskeleton));
140
 
        n = force_continuity(remove_short_cuts(n,.1));
141
 
        
142
 
        int nbCopies = 0;
143
 
        double scaling = 1;
144
 
        switch(type) {
145
 
            case PAPCT_REPEATED:
146
 
                nbCopies = static_cast<int>(floor((uskeleton.domain().extent() - toffset + xspace)/(pattBndsX.extent()+xspace)));
147
 
                pattBndsX = Interval(pattBndsX.min(),pattBndsX.max()+xspace);
148
 
                break;
149
 
                
150
 
            case PAPCT_SINGLE:
151
 
                nbCopies = (toffset + pattBndsX.extent() < uskeleton.domain().extent()) ? 1 : 0;
152
 
                break;
153
 
                
154
 
            case PAPCT_SINGLE_STRETCHED:
155
 
                nbCopies = 1;
156
 
                scaling = (uskeleton.domain().extent() - toffset)/pattBndsX.extent();
157
 
                break;
158
 
                
159
 
            case PAPCT_REPEATED_STRETCHED:
160
 
                // if uskeleton is closed:
161
 
                if(path_i.segs.front().at0() == path_i.segs.back().at1()){
162
 
                    nbCopies = static_cast<int>(std::floor((uskeleton.domain().extent() - toffset)/(pattBndsX.extent()+xspace)));
163
 
                    pattBndsX = Interval(pattBndsX.min(),pattBndsX.max()+xspace);
164
 
                    scaling = (uskeleton.domain().extent() - toffset)/(((double)nbCopies)*pattBndsX.extent());
165
 
                    // if not closed: no space at the end
 
106
    OptInterval pattBndsX = bounds_exact(x0);
 
107
    OptInterval pattBndsY = bounds_exact(y0);
 
108
    if (pattBndsX && pattBndsY) {
 
109
        x0 -= pattBndsX->min();
 
110
        y0 -= pattBndsY->middle();
 
111
 
 
112
        double xspace  = spacing;
 
113
        double noffset = normal_offset;
 
114
        double toffset = tang_offset;
 
115
        if (prop_units.get_value() && pattBndsY){
 
116
            xspace  *= pattBndsX->extent();
 
117
            noffset *= pattBndsY->extent();
 
118
            toffset *= pattBndsX->extent();
 
119
        }
 
120
 
 
121
        //Prevent more than 90% overlap...
 
122
        if (xspace < -pattBndsX->extent()*.9) {
 
123
            xspace = -pattBndsX->extent()*.9;
 
124
        }
 
125
        //TODO: dynamical update of parameter ranges?
 
126
        //if (prop_units.get_value()){
 
127
        //        spacing.param_set_range(-.9, NR_HUGE);
 
128
        //    }else{
 
129
        //        spacing.param_set_range(-pattBndsX.extent()*.9, NR_HUGE);
 
130
        //    }
 
131
 
 
132
        y0+=noffset;
 
133
 
 
134
        std::vector<Geom::Piecewise<Geom::D2<Geom::SBasis> > > paths_in;
 
135
        paths_in = split_at_discontinuities(pwd2_in);
 
136
 
 
137
        for (unsigned idx = 0; idx < paths_in.size(); idx++){
 
138
            Geom::Piecewise<Geom::D2<Geom::SBasis> > path_i = paths_in[idx];
 
139
            Piecewise<SBasis> x = x0;
 
140
            Piecewise<SBasis> y = y0;
 
141
            Piecewise<D2<SBasis> > uskeleton = arc_length_parametrization(path_i,2,.1);
 
142
            uskeleton = remove_short_cuts(uskeleton,.01);
 
143
            Piecewise<D2<SBasis> > n = rot90(derivative(uskeleton));
 
144
            n = force_continuity(remove_short_cuts(n,.1));
 
145
            
 
146
            int nbCopies = 0;
 
147
            double scaling = 1;
 
148
            switch(type) {
 
149
                case PAPCT_REPEATED:
 
150
                    nbCopies = static_cast<int>(floor((uskeleton.domain().extent() - toffset + xspace)/(pattBndsX->extent()+xspace)));
 
151
                    pattBndsX = Interval(pattBndsX->min(),pattBndsX->max()+xspace);
 
152
                    break;
 
153
                    
 
154
                case PAPCT_SINGLE:
 
155
                    nbCopies = (toffset + pattBndsX->extent() < uskeleton.domain().extent()) ? 1 : 0;
 
156
                    break;
 
157
                    
 
158
                case PAPCT_SINGLE_STRETCHED:
 
159
                    nbCopies = 1;
 
160
                    scaling = (uskeleton.domain().extent() - toffset)/pattBndsX->extent();
 
161
                    break;
 
162
                    
 
163
                case PAPCT_REPEATED_STRETCHED:
 
164
                    // if uskeleton is closed:
 
165
                    if(path_i.segs.front().at0() == path_i.segs.back().at1()){
 
166
                        nbCopies = static_cast<int>(std::floor((uskeleton.domain().extent() - toffset)/(pattBndsX->extent()+xspace)));
 
167
                        pattBndsX = Interval(pattBndsX->min(),pattBndsX->max()+xspace);
 
168
                        scaling = (uskeleton.domain().extent() - toffset)/(((double)nbCopies)*pattBndsX->extent());
 
169
                        // if not closed: no space at the end
 
170
                    }else{
 
171
                        nbCopies = static_cast<int>(std::floor((uskeleton.domain().extent() - toffset + xspace)/(pattBndsX->extent()+xspace)));
 
172
                        pattBndsX = Interval(pattBndsX->min(),pattBndsX->max()+xspace);
 
173
                        scaling = (uskeleton.domain().extent() - toffset)/(((double)nbCopies)*pattBndsX->extent() - xspace);
 
174
                    }
 
175
                    break;
 
176
                    
 
177
                default:
 
178
                    return pwd2_in;
 
179
            };
 
180
            
 
181
            double pattWidth = pattBndsX->extent() * scaling;
 
182
            
 
183
            if (scaling != 1.0) {
 
184
                x*=scaling;
 
185
            }
 
186
            if ( scale_y_rel.get_value() ) {
 
187
                y*=(scaling*prop_scale);
 
188
            } else {
 
189
                if (prop_scale != 1.0) y *= prop_scale;
 
190
            }
 
191
            x += toffset;
 
192
            
 
193
            double offs = 0;
 
194
            for (int i=0; i<nbCopies; i++){
 
195
                if (fuse_tolerance > 0){        
 
196
                    Geom::Piecewise<Geom::D2<Geom::SBasis> > output_piece = compose(uskeleton,x+offs)+y*compose(n,x+offs);
 
197
                    std::vector<Geom::Piecewise<Geom::D2<Geom::SBasis> > > splited_output_piece = split_at_discontinuities(output_piece);
 
198
                    pre_output.insert(pre_output.end(), splited_output_piece.begin(), splited_output_piece.end() );
166
199
                }else{
167
 
                    nbCopies = static_cast<int>(std::floor((uskeleton.domain().extent() - toffset + xspace)/(pattBndsX.extent()+xspace)));
168
 
                    pattBndsX = Interval(pattBndsX.min(),pattBndsX.max()+xspace);
169
 
                    scaling = (uskeleton.domain().extent() - toffset)/(((double)nbCopies)*pattBndsX.extent() - xspace);
 
200
                    output.concat(compose(uskeleton,x+offs)+y*compose(n,x+offs));
170
201
                }
171
 
                break;
172
 
                
173
 
            default:
174
 
                return pwd2_in;
175
 
        };
176
 
        
177
 
        double pattWidth = pattBndsX.extent() * scaling;
178
 
        
179
 
        if (scaling != 1.0) {
180
 
            x*=scaling;
181
 
        }
182
 
        if ( scale_y_rel.get_value() ) {
183
 
            y*=(scaling*prop_scale);
184
 
        } else {
185
 
            if (prop_scale != 1.0) y *= prop_scale;
186
 
        }
187
 
        x += toffset;
188
 
        
189
 
        double offs = 0;
190
 
        for (int i=0; i<nbCopies; i++){
191
 
            output.concat(compose(uskeleton,x+offs)+y*compose(n,x+offs));
192
 
            offs+=pattWidth;
193
 
        }
 
202
                offs+=pattWidth;
 
203
            }
 
204
        }
 
205
        if (fuse_tolerance > 0){        
 
206
            pre_output = fuse_nearby_ends(pre_output, fuse_tolerance);
 
207
            for (unsigned i=0; i<pre_output.size(); i++){
 
208
                output.concat(pre_output[i]);
 
209
            }
 
210
        }
 
211
        return output;
 
212
    } else {
 
213
        return pwd2_in;
194
214
    }
195
 
    return output;
196
215
}
197
216
 
198
217
LPEFreehandShape::LPEFreehandShape(LivePathEffectObject *lpeobject) : LPEPatternAlongPath(lpeobject)