~valavanisalex/ubuntu/oneiric/inkscape/inkscape_0.48.1-2ubuntu4

« back to all changes in this revision

Viewing changes to src/2geom/sbasis-to-bezier.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Kees Cook, Ted Gould, Kees Cook
  • Date: 2009-06-24 14:00:43 UTC
  • mfrom: (1.1.8 upstream)
  • Revision ID: james.westby@ubuntu.com-20090624140043-07stp20mry48hqup
Tags: 0.47~pre0-0ubuntu1
* New upstream release

[ Ted Gould ]
* debian/control: Adding libgsl0 and removing version specifics on boost

[ Kees Cook ]
* debian/watch: updated to run uupdate and mangle pre-release versions.
* Dropped patches that have been taken upstream:
  - 01_mips
  - 02-poppler-0.8.3
  - 03-chinese-inkscape
  - 05_fix_latex_patch
  - 06_gcc-4.4
  - 07_cdr2svg
  - 08_skip-bad-utf-on-pdf-import
  - 09_gtk-clist
  - 10_belarussian
  - 11_libpng
  - 12_desktop
  - 13_slider
  - 100_svg_import_improvements
  - 102_sp_pattern_painter_free
  - 103_bitmap_type_print

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* From Sanchez-Reyes 1997
2
 
   W_{j,k} = W_{n0j, n-k} = choose(n-2k-1, j-k)choose(2k+1,k)/choose(n,j)
3
 
     for k=0,...,q-1; j = k, ...,n-k-1
4
 
   W_{q,q} = 1 (n even)
5
 
 
6
 
This is wrong, it should read
7
 
   W_{j,k} = W_{n0j, n-k} = choose(n-2k-1, j-k)/choose(n,j)
8
 
     for k=0,...,q-1; j = k, ...,n-k-1
9
 
   W_{q,q} = 1 (n even)
10
 
 
11
 
*/
12
 
#include "sbasis-to-bezier.h"
13
 
#include "choose.h"
14
 
#include "svg-path.h"
 
1
/*
 
2
 * Symmetric Power Basis - Bernstein Basis conversion routines
 
3
 *
 
4
 * Authors:
 
5
 *      Marco Cecchetti <mrcekets at gmail.com>
 
6
 *      Nathan Hurst <njh@mail.csse.monash.edu.au>
 
7
 *
 
8
 * Copyright 2007-2008  authors
 
9
 *
 
10
 * This library is free software; you can redistribute it and/or
 
11
 * modify it either under the terms of the GNU Lesser General Public
 
12
 * License version 2.1 as published by the Free Software Foundation
 
13
 * (the "LGPL") or, at your option, under the terms of the Mozilla
 
14
 * Public License Version 1.1 (the "MPL"). If you do not alter this
 
15
 * notice, a recipient may use your version of this file under either
 
16
 * the MPL or the LGPL.
 
17
 *
 
18
 * You should have received a copy of the LGPL along with this library
 
19
 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
 
20
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
21
 * You should have received a copy of the MPL along with this library
 
22
 * in the file COPYING-MPL-1.1
 
23
 *
 
24
 * The contents of this file are subject to the Mozilla Public License
 
25
 * Version 1.1 (the "License"); you may not use this file except in
 
26
 * compliance with the License. You may obtain a copy of the License at
 
27
 * http://www.mozilla.org/MPL/
 
28
 *
 
29
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
 
30
 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
 
31
 * the specific language governing rights and limitations.
 
32
 */
 
33
 
 
34
 
 
35
#include <2geom/sbasis-to-bezier.h>
 
36
#include <2geom/d2.h>
 
37
#include <2geom/choose.h>
 
38
#include <2geom/svg-path.h>
 
39
#include <2geom/exception.h>
 
40
 
15
41
#include <iostream>
16
 
#include "exception.h"
17
 
 
18
 
namespace Geom{
19
 
 
20
 
double W(unsigned n, unsigned j, unsigned k) {
21
 
    unsigned q = (n+1)/2;
22
 
    if((n & 1) == 0 && j == q && k == q)
23
 
        return 1;
24
 
    if(k > n-k) return W(n, n-j, n-k);
25
 
    assert((k <= q));
26
 
    if(k >= q) return 0;
27
 
    //assert(!(j >= n-k));
28
 
    if(j >= n-k) return 0;
29
 
    //assert(!(j < k));
30
 
    if(j < k) return 0;
31
 
    return choose<double>(n-2*k-1, j-k) /
32
 
        choose<double>(n,j);
33
 
}
34
 
 
35
 
// this produces a degree 2q bezier from a degree k sbasis
36
 
Bezier
37
 
sbasis_to_bezier(SBasis const &B, unsigned q) {
38
 
    if(q == 0) {
39
 
        q = B.size();
40
 
        /*if(B.back()[0] == B.back()[1]) {
41
 
            n--;
42
 
            }*/
43
 
    }
44
 
    unsigned n = q*2;
45
 
    Bezier result = Bezier(Bezier::Order(n-1));
46
 
    if(q > B.size())
47
 
        q = B.size();
48
 
    n--;
49
 
    for(unsigned k = 0; k < q; k++) {
50
 
        for(unsigned j = 0; j <= n-k; j++) {
51
 
            result[j] += (W(n, j, k)*B[k][0] +
52
 
                          W(n, n-j, k)*B[k][1]);
53
 
        }
54
 
    }
55
 
    return result;
56
 
}
57
 
 
58
 
double mopi(int i) {
59
 
    return (i&1)?-1:1;
60
 
}
61
 
 
62
 
// this produces a degree k sbasis from a degree 2q bezier
63
 
SBasis
64
 
bezier_to_sbasis(Bezier const &B) {
65
 
    unsigned n = B.size();
66
 
    unsigned q = (n+1)/2;
67
 
    SBasis result;
68
 
    result.resize(q+1);
69
 
    for(unsigned k = 0; k < q; k++) {
70
 
        result[k][0] = result[k][1] = 0;
71
 
        for(unsigned j = 0; j <= n-k; j++) {
72
 
            result[k][0] += mopi(int(j)-int(k))*W(n, j, k)*B[j];
73
 
            result[k][1] += mopi(int(j)-int(k))*W(n, j, k)*B[j];
74
 
            //W(n, n-j, k)*B[k][1]);
75
 
        }
76
 
    }
77
 
    return result;
78
 
}
79
 
 
80
 
// this produces a 2q point bezier from a degree q sbasis
81
 
std::vector<Geom::Point>
82
 
sbasis_to_bezier(D2<SBasis> const &B, unsigned qq) {
83
 
    std::vector<Geom::Point> result;
84
 
    if(qq == 0) {
85
 
        qq = sbasis_size(B);
86
 
    }
87
 
    unsigned n = qq * 2;
88
 
    result.resize(n, Geom::Point(0,0));
89
 
    n--;
90
 
    for(unsigned dim = 0; dim < 2; dim++) {
91
 
        unsigned q = qq;
92
 
        if(q > B[dim].size())
93
 
            q = B[dim].size();
94
 
        for(unsigned k = 0; k < q; k++) {
95
 
            for(unsigned j = 0; j <= n-k; j++) {
96
 
                result[j][dim] += (W(n, j, k)*B[dim][k][0] +
97
 
                             W(n, n-j, k)*B[dim][k][1]);
98
 
                }
99
 
        }
100
 
    }
101
 
    return result;
102
 
}
 
42
 
 
43
 
 
44
 
 
45
 
 
46
namespace Geom
 
47
{
 
48
 
103
49
/*
104
 
template <unsigned order>
105
 
D2<Bezier<order> > sbasis_to_bezier(D2<SBasis> const &B) {
106
 
    return D2<Bezier<order> >(sbasis_to_bezier<order>(B[0]), sbasis_to_bezier<order>(B[1]));
107
 
}
108
 
*/
109
 
 
110
 
#if 0 // using old path
111
 
//std::vector<Geom::Point>
112
 
// mutating
113
 
void
114
 
subpath_from_sbasis(Geom::OldPathSetBuilder &pb, D2<SBasis> const &B, double tol, bool initial) {
115
 
    assert(B.is_finite());
116
 
    if(B.tail_error(2) < tol || B.size() == 2) { // nearly cubic enough
117
 
        if(B.size() == 1) {
118
 
            if (initial) {
119
 
                pb.start_subpath(Geom::Point(B[0][0][0], B[1][0][0]));
120
 
            }
121
 
            pb.push_line(Geom::Point(B[0][0][1], B[1][0][1]));
122
 
        } else {
123
 
            std::vector<Geom::Point> bez = sbasis_to_bezier(B, 2);
124
 
            if (initial) {
125
 
                pb.start_subpath(bez[0]);
126
 
            }
127
 
            pb.push_cubic(bez[1], bez[2], bez[3]);
128
 
        }
129
 
    } else {
130
 
        subpath_from_sbasis(pb, compose(B, Linear(0, 0.5)), tol, initial);
131
 
        subpath_from_sbasis(pb, compose(B, Linear(0.5, 1)), tol, false);
132
 
    }
133
 
}
134
 
 
 
50
 *  Symmetric Power Basis - Bernstein Basis conversion routines
 
51
 *
 
52
 *  some remark about precision:
 
53
 *  interval [0,1], subdivisions: 10^3
 
54
 *  - bezier_to_sbasis : up to degree ~72 precision is at least 10^-5
 
55
 *                       up to degree ~87 precision is at least 10^-3
 
56
 *  - sbasis_to_bezier : up to order ~63 precision is at least 10^-15
 
57
 *                       precision is at least 10^-14 even beyond order 200
 
58
 *
 
59
 *  interval [-1,1], subdivisions: 10^3
 
60
 *  - bezier_to_sbasis : up to degree ~21 precision is at least 10^-5
 
61
 *                       up to degree ~24 precision is at least 10^-3
 
62
 *  - sbasis_to_bezier : up to order ~11 precision is at least 10^-5
 
63
 *                       up to order ~13 precision is at least 10^-3
 
64
 *
 
65
 *  interval [-10,10], subdivisions: 10^3
 
66
 *  - bezier_to_sbasis : up to degree ~7 precision is at least 10^-5
 
67
 *                       up to degree ~8 precision is at least 10^-3
 
68
 *  - sbasis_to_bezier : up to order ~3 precision is at least 10^-5
 
69
 *                       up to order ~4 precision is at least 10^-3
 
70
 *
 
71
 *  references:
 
72
 *  this implementation is based on the following article:
 
73
 *  J.Sanchez-Reyes - The Symmetric Analogue of the Polynomial Power Basis
 
74
 */
 
75
 
 
76
inline
 
77
double binomial(unsigned int n, unsigned int k)
 
78
{
 
79
    return choose<double>(n, k);
 
80
}
 
81
 
 
82
inline
 
83
int sgn(unsigned int j, unsigned int k)
 
84
{
 
85
    assert (j >= k);
 
86
    // we are sure that j >= k
 
87
    return ((j-k) &  1u) ? -1 : 1;
 
88
}
 
89
 
 
90
 
 
91
/** Changes the basis of p to be bernstein.
 
92
 \param p the Symmetric basis polynomial
 
93
 \returns the Bernstein basis polynomial
 
94
 
 
95
 if the degree is even q is the order in the symmetrical power basis,
 
96
 if the degree is odd q is the order + 1
 
97
 n is always the polynomial degree, i. e. the Bezier order
 
98
 sz is the number of bezier handles.
 
99
*/
 
100
void sbasis_to_bezier (Bezier & bz, SBasis const& sb, size_t sz)
 
101
{
 
102
    size_t q, n;
 
103
    bool even;
 
104
    if (sz == 0)
 
105
    {
 
106
        q = sb.size();
 
107
        if (sb[q-1][0] == sb[q-1][1])
 
108
        {
 
109
            even = true;
 
110
            --q;
 
111
            n = 2*q;
 
112
        }
 
113
        else
 
114
        {
 
115
            even = false;
 
116
            n = 2*q-1;
 
117
        }
 
118
    }
 
119
    else
 
120
    {
 
121
        q = (sz > 2*sb.size()-1) ?  sb.size() : (sz+1)/2;
 
122
        n = sz-1;
 
123
        even = false;
 
124
    }
 
125
    bz.clear();
 
126
    bz.resize(n+1);
 
127
    double Tjk;
 
128
    for (size_t k = 0; k < q; ++k)
 
129
    {
 
130
        for (size_t j = k; j < n-k; ++j) // j <= n-k-1
 
131
        {
 
132
            Tjk = binomial(n-2*k-1, j-k);
 
133
            bz[j] += (Tjk * sb[k][0]);
 
134
            bz[n-j] += (Tjk * sb[k][1]); // n-k <-> [k][1]
 
135
        }
 
136
    }
 
137
    if (even)
 
138
    {
 
139
        bz[q] += sb[q][0];
 
140
    }
 
141
    // the resulting coefficients are with respect to the scaled Bernstein
 
142
    // basis so we need to divide them by (n, j) binomial coefficient
 
143
    for (size_t j = 1; j < n; ++j)
 
144
    {
 
145
        bz[j] /= binomial(n, j);
 
146
    }
 
147
    bz[0] = sb[0][0];
 
148
    bz[n] = sb[0][1];
 
149
}
 
150
 
 
151
/** Changes the basis of p to be Bernstein.
 
152
 \param p the D2 Symmetric basis polynomial
 
153
 \returns the D2 Bernstein basis polynomial
 
154
 
 
155
 sz is always the polynomial degree, i. e. the Bezier order
 
156
*/
 
157
void sbasis_to_bezier (std::vector<Point> & bz, D2<SBasis> const& sb, size_t sz)
 
158
{
 
159
    Bezier bzx, bzy;
 
160
    if(sz == 0) {
 
161
        sz = std::max(sb[X].size(), sb[Y].size())*2;
 
162
    }
 
163
    sbasis_to_bezier(bzx, sb[X], sz);
 
164
    sbasis_to_bezier(bzy, sb[Y], sz);
 
165
    assert(bzx.size() == bzy.size());
 
166
    size_t n = (bzx.size() >= bzy.size()) ? bzx.size() : bzy.size();
 
167
 
 
168
    bz.resize(n, Point(0,0));
 
169
    for (size_t i = 0; i < bzx.size(); ++i)
 
170
    {
 
171
        bz[i][X] = bzx[i];
 
172
    }
 
173
    for (size_t i = 0; i < bzy.size(); ++i)
 
174
    {
 
175
        bz[i][Y] = bzy[i];
 
176
    }
 
177
}
 
178
 
 
179
 
 
180
/** Changes the basis of p to be sbasis.
 
181
 \param p the Bernstein basis polynomial
 
182
 \returns the Symmetric basis polynomial
 
183
 
 
184
 if the degree is even q is the order in the symmetrical power basis,
 
185
 if the degree is odd q is the order + 1
 
186
 n is always the polynomial degree, i. e. the Bezier order
 
187
*/
 
188
void bezier_to_sbasis (SBasis & sb, Bezier const& bz)
 
189
{
 
190
    size_t n = bz.order();
 
191
    size_t q = (n+1) / 2;
 
192
    size_t even = (n & 1u) ? 0 : 1;
 
193
    sb.clear();
 
194
    sb.resize(q + even, Linear(0, 0));
 
195
    double Tjk;
 
196
    for (size_t k = 0; k < q; ++k)
 
197
    {
 
198
        for (size_t j = k; j < q; ++j)
 
199
        {
 
200
            Tjk = sgn(j, k) * binomial(n-j-k, j-k) * binomial(n, k);
 
201
            sb[j][0] += (Tjk * bz[k]);
 
202
            sb[j][1] += (Tjk * bz[n-k]); // n-j <-> [j][1]
 
203
        }
 
204
        for (size_t j = k+1; j < q; ++j)
 
205
        {
 
206
            Tjk = sgn(j, k) * binomial(n-j-k-1, j-k-1) * binomial(n, k);
 
207
            sb[j][0] += (Tjk * bz[n-k]);
 
208
            sb[j][1] += (Tjk * bz[k]);   // n-j <-> [j][1]
 
209
        }
 
210
    }
 
211
    if (even)
 
212
    {
 
213
        for (size_t k = 0; k < q; ++k)
 
214
        {
 
215
            Tjk = sgn(q,k) * binomial(n, k);
 
216
            sb[q][0] += (Tjk * (bz[k] + bz[n-k]));
 
217
        }
 
218
        sb[q][0] += (binomial(n, q) * bz[q]);
 
219
        sb[q][1] = sb[q][0];
 
220
    }
 
221
    sb[0][0] = bz[0];
 
222
    sb[0][1] = bz[n];
 
223
}
 
224
 
 
225
 
 
226
/** Changes the basis of d2 p to be sbasis.
 
227
 \param p the d2 Bernstein basis polynomial
 
228
 \returns the d2 Symmetric basis polynomial
 
229
 
 
230
 if the degree is even q is the order in the symmetrical power basis,
 
231
 if the degree is odd q is the order + 1
 
232
 n is always the polynomial degree, i. e. the Bezier order
 
233
*/
 
234
void bezier_to_sbasis (D2<SBasis> & sb, std::vector<Point> const& bz)
 
235
{
 
236
    size_t n = bz.size() - 1;
 
237
    size_t q = (n+1) / 2;
 
238
    size_t even = (n & 1u) ? 0 : 1;
 
239
    sb[X].clear();
 
240
    sb[Y].clear();
 
241
    sb[X].resize(q + even, Linear(0, 0));
 
242
    sb[Y].resize(q + even, Linear(0, 0));
 
243
    double Tjk;
 
244
    for (size_t k = 0; k < q; ++k)
 
245
    {
 
246
        for (size_t j = k; j < q; ++j)
 
247
        {
 
248
            Tjk = sgn(j, k) * binomial(n-j-k, j-k) * binomial(n, k);
 
249
            sb[X][j][0] += (Tjk * bz[k][X]);
 
250
            sb[X][j][1] += (Tjk * bz[n-k][X]);
 
251
            sb[Y][j][0] += (Tjk * bz[k][Y]);
 
252
            sb[Y][j][1] += (Tjk * bz[n-k][Y]);
 
253
        }
 
254
        for (size_t j = k+1; j < q; ++j)
 
255
        {
 
256
            Tjk = sgn(j, k) * binomial(n-j-k-1, j-k-1) * binomial(n, k);
 
257
            sb[X][j][0] += (Tjk * bz[n-k][X]);
 
258
            sb[X][j][1] += (Tjk * bz[k][X]);
 
259
            sb[Y][j][0] += (Tjk * bz[n-k][Y]);
 
260
            sb[Y][j][1] += (Tjk * bz[k][Y]);
 
261
        }
 
262
    }
 
263
    if (even)
 
264
    {
 
265
        for (size_t k = 0; k < q; ++k)
 
266
        {
 
267
            Tjk = sgn(q,k) * binomial(n, k);
 
268
            sb[X][q][0] += (Tjk * (bz[k][X] + bz[n-k][X]));
 
269
            sb[Y][q][0] += (Tjk * (bz[k][Y] + bz[n-k][Y]));
 
270
        }
 
271
        sb[X][q][0] += (binomial(n, q) * bz[q][X]);
 
272
        sb[X][q][1] = sb[X][q][0];
 
273
        sb[Y][q][0] += (binomial(n, q) * bz[q][Y]);
 
274
        sb[Y][q][1] = sb[Y][q][0];
 
275
    }
 
276
    sb[X][0][0] = bz[0][X];
 
277
    sb[X][0][1] = bz[n][X];
 
278
    sb[Y][0][0] = bz[0][Y];
 
279
    sb[Y][0][1] = bz[n][Y];
 
280
}
 
281
 
 
282
 
 
283
}  // end namespace Geom
 
284
 
 
285
 
 
286
#if 0 
135
287
/*
136
288
* This version works by inverting a reasonable upper bound on the error term after subdividing the
137
289
* curve at $a$.  We keep biting off pieces until there is no more curve left.
138
 
 
290
*
139
291
* Derivation: The tail of the power series is $a_ks^k + a_{k+1}s^{k+1} + \ldots = e$.  A
140
292
* subdivision at $a$ results in a tail error of $e*A^k, A = (1-a)a$.  Let this be the desired
141
293
* tolerance tol $= e*A^k$ and invert getting $A = e^{1/k}$ and $a = 1/2 - \sqrt{1/4 - A}$
144
296
subpath_from_sbasis_incremental(Geom::OldPathSetBuilder &pb, D2<SBasis> B, double tol, bool initial) {
145
297
    const unsigned k = 2; // cubic bezier
146
298
    double te = B.tail_error(k);
147
 
    assert(B[0].is_finite());
148
 
    assert(B[1].is_finite());
149
 
    
 
299
    assert(B[0].IS_FINITE());
 
300
    assert(B[1].IS_FINITE());
 
301
 
150
302
    //std::cout << "tol = " << tol << std::endl;
151
303
    while(1) {
152
304
        double A = std::sqrt(tol/te); // pow(te, 1./k)
169
321
          initial = false;
170
322
        }
171
323
        pb.push_cubic(bez[1], bez[2], bez[3]);
172
 
        
 
324
 
173
325
// move to next piece of curve
174
326
        if(a >= 1) break;
175
 
        B = compose(B, Linear(a, 1)); 
 
327
        B = compose(B, Linear(a, 1));
176
328
        te = B.tail_error(k);
177
329
    }
178
330
}
179
331
 
180
332
#endif
181
333
 
182
 
void build_from_sbasis(Geom::PathBuilder &pb, D2<SBasis> const &B, double tol) {
 
334
namespace Geom{
 
335
 
 
336
/** Make a path from a d2 sbasis.
 
337
 \param p the d2 Symmetric basis polynomial
 
338
 \returns a Path
 
339
 
 
340
  If only_cubicbeziers is true, the resulting path may only contain CubicBezier curves.
 
341
*/
 
342
void build_from_sbasis(Geom::PathBuilder &pb, D2<SBasis> const &B, double tol, bool only_cubicbeziers) {
183
343
    if (!B.isFinite()) {
184
 
        throwException("assertion failed: B.isFinite()");
 
344
        THROW_EXCEPTION("assertion failed: B.isFinite()");
185
345
    }
186
346
    if(tail_error(B, 2) < tol || sbasis_size(B) == 2) { // nearly cubic enough
187
 
        if(sbasis_size(B) <= 1) {
 
347
        if( !only_cubicbeziers && (sbasis_size(B) <= 1) ) {
188
348
            pb.lineTo(B.at1());
189
349
        } else {
190
 
            std::vector<Geom::Point> bez = sbasis_to_bezier(B, 2);
 
350
            std::vector<Geom::Point> bez;
 
351
            sbasis_to_bezier(bez, B, 4);
191
352
            pb.curveTo(bez[1], bez[2], bez[3]);
192
353
        }
193
354
    } else {
194
 
        build_from_sbasis(pb, compose(B, Linear(0, 0.5)), tol);
195
 
        build_from_sbasis(pb, compose(B, Linear(0.5, 1)), tol);
 
355
        build_from_sbasis(pb, compose(B, Linear(0, 0.5)), tol, only_cubicbeziers);
 
356
        build_from_sbasis(pb, compose(B, Linear(0.5, 1)), tol, only_cubicbeziers);
196
357
    }
197
358
}
198
359
 
 
360
/** Make a path from a d2 sbasis.
 
361
 \param p the d2 Symmetric basis polynomial
 
362
 \returns a Path
 
363
 
 
364
  If only_cubicbeziers is true, the resulting path may only contain CubicBezier curves.
 
365
*/
199
366
Path
200
 
path_from_sbasis(D2<SBasis> const &B, double tol) {
 
367
path_from_sbasis(D2<SBasis> const &B, double tol, bool only_cubicbeziers) {
201
368
    PathBuilder pb;
202
369
    pb.moveTo(B.at0());
203
 
    build_from_sbasis(pb, B, tol);
 
370
    build_from_sbasis(pb, B, tol, only_cubicbeziers);
204
371
    pb.finish();
205
372
    return pb.peek().front();
206
373
}
207
374
 
208
 
//TODO: some of this logic should be lifted into svg-path
 
375
/** Make a path from a d2 sbasis.
 
376
 \param p the d2 Symmetric basis polynomial
 
377
 \returns a Path
 
378
 
 
379
  If only_cubicbeziers is true, the resulting path may only contain CubicBezier curves.
 
380
 TODO: some of this logic should be lifted into svg-path
 
381
*/
209
382
std::vector<Geom::Path>
210
 
path_from_piecewise(Geom::Piecewise<Geom::D2<Geom::SBasis> > const &B, double tol) {
 
383
path_from_piecewise(Geom::Piecewise<Geom::D2<Geom::SBasis> > const &B, double tol, bool only_cubicbeziers) {
211
384
    Geom::PathBuilder pb;
212
385
    if(B.size() == 0) return pb.peek();
213
386
    Geom::Point start = B[0].at0();
216
389
        if(i+1 == B.size() || !are_near(B[i+1].at0(), B[i].at1(), tol)) {
217
390
            //start of a new path
218
391
            if(are_near(start, B[i].at1()) && sbasis_size(B[i]) <= 1) {
219
 
                //last line seg already there
 
392
                pb.closePath();
 
393
                //last line seg already there (because of .closePath())
220
394
                goto no_add;
221
395
            }
222
 
            build_from_sbasis(pb, B[i], tol);
 
396
            build_from_sbasis(pb, B[i], tol, only_cubicbeziers);
223
397
            if(are_near(start, B[i].at1())) {
224
 
                //it's closed
 
398
                //it's closed, the last closing segment was not a straight line so it needed to be added, but still make it closed here with degenerate straight line.
225
399
                pb.closePath();
226
400
            }
227
401
          no_add:
229
403
            start = B[i+1].at0();
230
404
            pb.moveTo(start);
231
405
        } else {
232
 
            build_from_sbasis(pb, B[i], tol);
 
406
            build_from_sbasis(pb, B[i], tol, only_cubicbeziers);
233
407
        }
234
408
    }
235
409
    pb.finish();
236
410
    return pb.peek();
237
411
}
238
412
 
239
 
};
 
413
}
240
414
 
241
415
/*
242
416
  Local Variables: