Subversion Repositories Scribus

Rev

Rev 20026 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
15347 fschmid 1
/*
2
 * Path - Series of continuous curves
12065 fschmid 3
 *
15347 fschmid 4
 * Copyright 2007  MenTaLguY <mental@rydia.net>
12065 fschmid 5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it either under the terms of the GNU Lesser General Public
8
 * License version 2.1 as published by the Free Software Foundation
9
 * (the "LGPL") or, at your option, under the terms of the Mozilla
10
 * Public License Version 1.1 (the "MPL"). If you do not alter this
11
 * notice, a recipient may use your version of this file under either
12
 * the MPL or the LGPL.
13
 *
14
 * You should have received a copy of the LGPL along with this library
15
 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
18122 mrdocs 16
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
12065 fschmid 17
 * You should have received a copy of the MPL along with this library
18
 * in the file COPYING-MPL-1.1
19
 *
20
 * The contents of this file are subject to the Mozilla Public License
21
 * Version 1.1 (the "License"); you may not use this file except in
22
 * compliance with the License. You may obtain a copy of the License at
23
 * http://www.mozilla.org/MPL/
24
 *
25
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
26
 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
27
 * the specific language governing rights and limitations.
28
 */
29
 
15347 fschmid 30
#ifndef SEEN_GEOM_PATH_H
31
#define SEEN_GEOM_PATH_H
12065 fschmid 32
 
15347 fschmid 33
#include "point.h"
34
#include <iterator>
35
#include <algorithm>
36
#include "exception.h"
37
#include "d2.h"
38
#include "matrix.h"
39
#include "bezier.h"
40
#include "crossing.h"
41
#include "utils.h"
12065 fschmid 42
 
15347 fschmid 43
namespace Geom {
12065 fschmid 44
 
15347 fschmid 45
class Curve;
12065 fschmid 46
 
15347 fschmid 47
struct CurveHelpers {
48
protected:
49
  static int root_winding(Curve const &c, Point p);
50
};
12065 fschmid 51
 
15347 fschmid 52
class Curve : private CurveHelpers {
53
public:
54
  virtual ~Curve() {}
12065 fschmid 55
 
15347 fschmid 56
  virtual Point initialPoint() const = 0;
57
  virtual Point finalPoint() const = 0;
12065 fschmid 58
 
15347 fschmid 59
  virtual bool isDegenerate() const = 0;
12065 fschmid 60
 
15347 fschmid 61
  virtual Curve *duplicate() const = 0;
12065 fschmid 62
 
15347 fschmid 63
  virtual Rect boundsFast() const = 0;
64
  virtual Rect boundsExact() const = 0;
65
  virtual Rect boundsLocal(Interval i, unsigned deg) const = 0;
66
  Rect boundsLocal(Interval i) const { return boundsLocal(i, 0); }
12065 fschmid 67
 
15347 fschmid 68
  virtual std::vector<double> roots(double v, Dim2 d) const = 0;
12065 fschmid 69
 
15347 fschmid 70
  virtual int winding(Point p) const { return root_winding(*this, p); }
12065 fschmid 71
 
15347 fschmid 72
  //mental: review these
73
  virtual Curve *portion(double f, double t) const = 0;
74
  virtual Curve *reverse() const { return portion(1, 0); }
75
  virtual Curve *derivative() const = 0;
12065 fschmid 76
 
15347 fschmid 77
  virtual void setInitial(Point v) = 0;
78
  virtual void setFinal(Point v) = 0;
79
 
80
  virtual Curve *transformed(Matrix const &m) const = 0;
81
 
82
  virtual Point pointAt(Coord t) const { return pointAndDerivatives(t, 1).front(); }
83
  virtual Coord valueAt(Coord t, Dim2 d) const { return pointAt(t)[d]; }
84
  virtual std::vector<Point> pointAndDerivatives(Coord t, unsigned n) const = 0;
85
  virtual D2<SBasis> toSBasis() const = 0;
86
};
87
 
88
class SBasisCurve : public Curve {
89
private:
90
  SBasisCurve();
91
  D2<SBasis> inner;
12065 fschmid 92
public:
15347 fschmid 93
  explicit SBasisCurve(D2<SBasis> const &sb) : inner(sb) {}
94
  explicit SBasisCurve(Curve const &other) : inner(other.toSBasis()) {}
95
  Curve *duplicate() const { return new SBasisCurve(*this); }
96
 
97
  Point initialPoint() const    { return inner.at0(); }
98
  Point finalPoint() const      { return inner.at1(); }
99
  bool isDegenerate() const     { return inner.isConstant(); }
100
  Point pointAt(Coord t) const  { return inner.valueAt(t); }
101
  std::vector<Point> pointAndDerivatives(Coord t, unsigned n) const {
102
      return inner.valueAndDerivatives(t, n);
12065 fschmid 103
  }
15347 fschmid 104
  double valueAt(Coord t, Dim2 d) const { return inner[d].valueAt(t); }
105
 
106
  void setInitial(Point v) { for(unsigned d = 0; d < 2; d++) { inner[d][0][0] = v[d]; } }
107
  void setFinal(Point v)   { for(unsigned d = 0; d < 2; d++) { inner[d][0][1] = v[d]; } }
108
 
109
  Rect boundsFast() const  { return bounds_fast(inner); }
110
  Rect boundsExact() const { return bounds_exact(inner); }
111
  Rect boundsLocal(Interval i, unsigned deg) const { return bounds_local(inner, i, deg); }
112
 
113
  std::vector<double> roots(double v, Dim2 d) const { return Geom::roots(inner[d] - v); }
114
 
115
  Curve *portion(double f, double t) const {
116
    return new SBasisCurve(Geom::portion(inner, f, t));
12065 fschmid 117
  }
118
 
15347 fschmid 119
  Curve *transformed(Matrix const &m) const {
120
    return new SBasisCurve(inner * m);
12065 fschmid 121
  }
122
 
15347 fschmid 123
  Curve *derivative() const {
124
    return new SBasisCurve(Geom::derivative(inner));
12065 fschmid 125
  }
15347 fschmid 126
 
127
  D2<SBasis> toSBasis() const { return inner; }
128
 
129
};
130
 
131
template <unsigned order>
132
class BezierCurve : public Curve {
133
private:
134
  D2<Bezier > inner;
135
public:
136
  template <unsigned required_degree>
137
  static void assert_degree(BezierCurve<required_degree> const *) {}
138
 
139
  BezierCurve() : inner(Bezier::Order(order), Bezier::Order(order)) {
12065 fschmid 140
  }
141
 
15347 fschmid 142
  explicit BezierCurve(D2<Bezier > const &x) : inner(x) {}
143
 
144
  BezierCurve(Bezier x, Bezier y) : inner(x, y) {}
145
 
146
  // default copy
147
  // default assign
148
 
149
  BezierCurve(Point c0, Point c1) {
150
    assert_degree<1>(this);
151
    for(unsigned d = 0; d < 2; d++)
152
        inner[d] = Bezier(c0[d], c1[d]);
12065 fschmid 153
  }
15347 fschmid 154
 
155
  BezierCurve(Point c0, Point c1, Point c2) {
156
    assert_degree<2>(this);
157
    for(unsigned d = 0; d < 2; d++)
158
        inner[d] = Bezier(c0[d], c1[d], c2[d]);
12065 fschmid 159
  }
160
 
15347 fschmid 161
  BezierCurve(Point c0, Point c1, Point c2, Point c3) {
162
    assert_degree<3>(this);
163
    for(unsigned d = 0; d < 2; d++)
164
        inner[d] = Bezier(c0[d], c1[d], c2[d], c3[d]);
165
  }
12065 fschmid 166
 
15347 fschmid 167
  unsigned degree() const { return order; }
168
 
169
  Curve *duplicate() const { return new BezierCurve(*this); }
170
 
171
  Point initialPoint() const { return inner.at0(); }
172
  Point finalPoint() const { return inner.at1(); }
173
 
174
  bool isDegenerate() const { return inner.isConstant(); }
175
 
176
  void setInitial(Point v) { setPoint(0, v); }
177
  void setFinal(Point v)   { setPoint(1, v); }
178
 
179
  void setPoint(unsigned ix, Point v) { inner[X].setPoint(ix, v[X]); inner[Y].setPoint(ix, v[Y]); }
180
  Point const operator[](unsigned ix) const { return Point(inner[X][ix], inner[Y][ix]); }
181
 
182
  Rect boundsFast() const { return bounds_fast(inner); }
183
  Rect boundsExact() const { return bounds_exact(inner); }
184
  Rect boundsLocal(Interval i, unsigned deg) const {
185
      if(i.min() == 0 && i.max() == 1) return boundsFast();
186
      if(deg == 0) return bounds_local(inner, i);
187
      // TODO: UUUUUUGGGLLY
188
      if(deg == 1 && order > 1) return Rect(bounds_local(Geom::derivative(inner[X]), i),
189
                                            bounds_local(Geom::derivative(inner[Y]), i));
190
      return Rect(Interval(0,0), Interval(0,0));
191
  }
192
//TODO: local
193
 
194
//TODO: implement next 3 natively
195
  int winding(Point p) const {
196
    return SBasisCurve(toSBasis()).winding(p);
197
  }
198
 
199
  std::vector<double>
200
  roots(double v, Dim2 d) const {
201
      return (inner[d] - v).roots();
202
  }
203
 
204
  void setPoints(std::vector<Point> ps) {
205
    for(unsigned i = 0; i <= order; i++) {
206
      setPoint(i, ps[i]);
207
    }
208
  }
209
  std::vector<Point> points() const { return bezier_points(inner); }
210
 
211
  std::pair<BezierCurve<order>, BezierCurve<order> > subdivide(Coord t) const {
212
    std::pair<Bezier, Bezier > sx = inner[X].subdivide(t), sy = inner[Y].subdivide(t);
213
    return std::pair<BezierCurve<order>, BezierCurve<order> >(
214
               BezierCurve<order>(sx.first, sy.first),
215
               BezierCurve<order>(sx.second, sy.second));
216
  }
217
 
218
  Curve *portion(double f, double t) const {
219
    return new BezierCurve(Geom::portion(inner, f, t));
220
  }
221
 
222
  Curve *reverse() const {
223
    return new BezierCurve(Geom::reverse(inner));
224
  }
225
 
226
  Curve *transformed(Matrix const &m) const {
227
    BezierCurve *ret = new BezierCurve();
228
    std::vector<Point> ps = points();
229
    for(unsigned i = 0;  i <= order; i++) ps[i] = ps[i] * m;
230
    ret->setPoints(ps);
231
    return ret;
232
  }
233
 
234
  Curve *derivative() const {
235
     if(order > 1)
236
        return new BezierCurve<order-1>(Geom::derivative(inner[X]), Geom::derivative(inner[Y]));
237
     else if (order == 1) {
238
        double dx = inner[X][1] - inner[X][0], dy = inner[Y][1] - inner[Y][0];
239
        if(dx == 0) return new BezierCurve<1>(Point(0,0), Point(0,0));
240
        double slope = dy / dx;
241
        Geom::Point pnt;
242
        if(slope == 0) pnt = Geom::Point(0, 0); else pnt = Geom::Point(slope, 1./slope);
243
        return new BezierCurve<1>(pnt, pnt);
244
     }
245
  }
246
 
247
  Point pointAt(double t) const { return inner.valueAt(t); }
248
  std::vector<Point> pointAndDerivatives(Coord t, unsigned n) const { return inner.valueAndDerivatives(t, n); }
249
 
250
  double valueAt(double t, Dim2 d) const { return inner[d].valueAt(t); }
251
 
252
  D2<SBasis> toSBasis() const {return inner.toSBasis(); }
253
 
24687 jghali 254
// #16605: does not seem used at triggers build error with clang 12.0.1
255
//protected:
256
//  BezierCurve(Point c[]) {
257
//    Coord x[order+1], y[order+1];
258
//    for(unsigned i = 0; i <= order; i++) {
259
//        x[i] = c[i][X]; y[i] = c[i][Y];
260
//    }
261
//    inner = Bezier(x, y);
262
//  }
12065 fschmid 263
};
264
 
15347 fschmid 265
// BezierCurve<0> is meaningless; specialize it out
266
template<> class BezierCurve<0> : public BezierCurve<1> { public: BezierCurve(); BezierCurve(Bezier x, Bezier y) {}; };
267
 
268
typedef BezierCurve<1> LineSegment;
269
typedef BezierCurve<2> QuadraticBezier;
270
typedef BezierCurve<3> CubicBezier;
271
 
272
class SVGEllipticalArc : public Curve {
12065 fschmid 273
public:
15347 fschmid 274
  SVGEllipticalArc() {}
12065 fschmid 275
 
15347 fschmid 276
  SVGEllipticalArc(Point initial, double rx, double ry,
277
                   double x_axis_rotation, bool large_arc,
278
                   bool sweep, Point final)
279
  : initial_(initial), rx_(rx), ry_(ry), x_axis_rotation_(x_axis_rotation),
280
    large_arc_(large_arc), sweep_(sweep), final_(final)
281
  {}
12065 fschmid 282
 
15347 fschmid 283
  Curve *duplicate() const { return new SVGEllipticalArc(*this); }
284
 
285
  Point initialPoint() const { return initial_; }
286
  Point finalPoint() const { return final_; }
287
 
288
  void setInitial(Point v) { initial_ = v; }
289
  void setFinal(Point v) { final_ = v; }
290
 
291
  //TODO: implement funcs
292
 
293
  bool isDegenerate() const { return toSBasis().isConstant(); }
294
  Rect boundsFast() const;
295
  Rect boundsExact() const;
296
  Rect boundsLocal(Interval i, unsigned deg) const;
297
 
298
  int winding(Point p) const {
299
    return SBasisCurve(toSBasis()).winding(p);
300
  }
301
 
302
  std::vector<double> roots(double v, Dim2 d) const;
303
 
304
  inline std::pair<SVGEllipticalArc, SVGEllipticalArc>
305
  subdivide(Coord t) {
306
    SVGEllipticalArc a(*this), b(*this);
307
    a.final_ = b.initial_ = pointAt(t);
308
    return std::pair<SVGEllipticalArc, SVGEllipticalArc>(a, b);
309
  }
310
 
311
// TODO: how are the flags affected by reducing an arc from more than 180deg to less than 180deg?
312
  Curve *portion(double f, double t) const {
313
    SVGEllipticalArc *ret = new SVGEllipticalArc (*this);
314
    ret->initial_ = pointAt(f);
315
    ret->final_ = pointAt(t);
316
    return ret;
317
  }
318
 
319
// TODO: incomplete/buggy
20026 avox 320
  Curve *reverse(/*double f, double t*/) const {
15347 fschmid 321
    SVGEllipticalArc *ret = new SVGEllipticalArc (*this);
322
    ret->initial_ = final_;
323
    ret->final_ = initial_;
324
    return ret;
325
  }
326
 
327
  //TODO: this next def isn't right
328
  Curve *transformed(Matrix const & m) const {
329
    SVGEllipticalArc *ret = new SVGEllipticalArc (*this);
330
    ret->initial_ = initial_ * m;
331
    ret->final_ = final_ * m;
332
    return ret;
333
  }
334
 
335
  Curve *derivative() const { throwNotImplemented(0); }
336
 
337
  std::vector<Point> pointAndDerivatives(Coord t, unsigned n) const;
338
 
339
  D2<SBasis> toSBasis() const;
340
 
12065 fschmid 341
private:
15347 fschmid 342
  Point initial_;
343
  double rx_;
344
  double ry_;
345
  double x_axis_rotation_;
346
  bool large_arc_;
347
  bool sweep_;
348
  Point final_;
12065 fschmid 349
};
350
 
15347 fschmid 351
template <typename IteratorImpl>
352
class BaseIterator
353
: public std::iterator<std::forward_iterator_tag, Curve const>
354
{
12065 fschmid 355
public:
15347 fschmid 356
  BaseIterator() {}
12065 fschmid 357
 
15347 fschmid 358
  // default construct
359
  // default copy
12065 fschmid 360
 
15347 fschmid 361
  bool operator==(BaseIterator const &other) {
362
    return other.impl_ == impl_;
12065 fschmid 363
  }
15347 fschmid 364
  bool operator!=(BaseIterator const &other) {
365
    return other.impl_ != impl_;
366
  }
12065 fschmid 367
 
15347 fschmid 368
  Curve const &operator*() const { return **impl_; }
369
  Curve const *operator->() const { return *impl_; }
370
 
371
  BaseIterator &operator++() {
372
    ++impl_;
373
    return *this;
374
  }
375
 
376
  BaseIterator operator++(int) {
377
    BaseIterator old=*this;
378
    ++(*this);
379
    return old;
380
  }
381
 
12065 fschmid 382
private:
15347 fschmid 383
  BaseIterator(IteratorImpl const &pos) : impl_(pos) {}
384
 
385
  IteratorImpl impl_;
386
  friend class Path;
12065 fschmid 387
};
388
 
15347 fschmid 389
template <typename Iterator>
390
class DuplicatingIterator
391
: public std::iterator<std::input_iterator_tag, Curve *>
392
{
393
public:
394
  DuplicatingIterator() {}
395
  DuplicatingIterator(Iterator const &iter) : impl_(iter) {}
12065 fschmid 396
 
15347 fschmid 397
  bool operator==(DuplicatingIterator const &other) {
398
    return other.impl_ == impl_;
399
  }
400
  bool operator!=(DuplicatingIterator const &other) {
401
    return other.impl_ != impl_;
402
  }
403
 
404
  Curve *operator*() const { return (*impl_)->duplicate(); }
405
 
406
  DuplicatingIterator &operator++() {
407
    ++impl_;
408
    return *this;
409
  }
410
  DuplicatingIterator operator++(int) {
411
    DuplicatingIterator old=*this;
412
    ++(*this);
413
    return old;
414
  }
415
 
416
private:
417
  Iterator impl_;
418
};
419
 
12065 fschmid 420
class Path {
15347 fschmid 421
private:
422
  typedef std::vector<Curve *> Sequence;
423
 
12065 fschmid 424
public:
15347 fschmid 425
  typedef BaseIterator<Sequence::iterator> iterator;
426
  typedef BaseIterator<Sequence::const_iterator> const_iterator;
12065 fschmid 427
  typedef Sequence::size_type size_type;
428
  typedef Sequence::difference_type difference_type;
429
 
15347 fschmid 430
  Path()
431
  : final_(new LineSegment()), closed_(false)
432
  {
433
    curves_.push_back(final_);
434
  }
12065 fschmid 435
 
15347 fschmid 436
  Path(Path const &other)
437
  : final_(new LineSegment()), closed_(other.closed_)
12065 fschmid 438
  {
15347 fschmid 439
    curves_.push_back(final_);
440
    insert(begin(), other.begin(), other.end());
12065 fschmid 441
  }
442
 
15347 fschmid 443
  explicit Path(Point p)
444
  : final_(new LineSegment(p, p)), closed_(false)
12065 fschmid 445
  {
15347 fschmid 446
    curves_.push_back(final_);
12065 fschmid 447
  }
448
 
15347 fschmid 449
  template <typename Impl>
450
  Path(BaseIterator<Impl> first, BaseIterator<Impl> last, bool closed=false)
20026 avox 451
  : final_(new LineSegment()), closed_(closed)
15347 fschmid 452
  {
453
    curves_.push_back(final_);
454
    insert(begin(), first, last);
12065 fschmid 455
  }
456
 
15347 fschmid 457
  virtual ~Path() {
458
      delete_range(curves_.begin(), curves_.end()-1);
459
      delete final_;
12065 fschmid 460
  }
461
 
15347 fschmid 462
  Path &operator=(Path const &other) {
463
    clear();
464
    insert(begin(), other.begin(), other.end());
465
    close(other.closed_);
466
    return *this;
12065 fschmid 467
  }
468
 
15347 fschmid 469
  void swap(Path &other);
12065 fschmid 470
 
15347 fschmid 471
  Curve const &operator[](unsigned i) const { return *curves_[i]; }
472
 
473
  iterator begin() { return curves_.begin(); }
474
  iterator end() { return curves_.end()-1; }
475
 
476
  Curve const &front() const { return *curves_[0]; }
477
  Curve const &back() const { return *curves_[curves_.size()-2]; }
478
 
479
  const_iterator begin() const { return curves_.begin(); }
480
  const_iterator end() const { return curves_.end()-1; }
481
 
482
  const_iterator end_open() const { return curves_.end()-1; }
483
  const_iterator end_closed() const { return curves_.end(); }
12065 fschmid 484
  const_iterator end_default() const {
485
    return ( closed_ ? end_closed() : end_open() );
486
  }
487
 
15347 fschmid 488
  size_type size() const { return curves_.size()-1; }
489
  size_type max_size() const { return curves_.max_size()-1; }
12065 fschmid 490
 
15347 fschmid 491
  bool empty() const { return curves_.size() == 1; }
12065 fschmid 492
  bool closed() const { return closed_; }
493
  void close(bool closed=true) { closed_ = closed; }
494
 
15347 fschmid 495
  Rect boundsFast() const;
496
  Rect boundsExact() const;
12065 fschmid 497
 
498
  Piecewise<D2<SBasis> > toPwSb() const {
499
    Piecewise<D2<SBasis> > ret;
500
    ret.push_cut(0);
501
    unsigned i = 1;
15347 fschmid 502
    // ignore that path is closed or open. pw<d2<>> is always open.
503
    for(const_iterator it = begin(); it != end(); ++it) {
12065 fschmid 504
      if (!it->isDegenerate()) {
505
        ret.push(it->toSBasis(), i++);
506
      }
507
    }
508
    return ret;
509
  }
510
 
15347 fschmid 511
  Path operator*(Matrix const &m) const {
512
    Path ret;
513
    for(const_iterator it = begin(); it != end(); ++it) {
514
      Curve *temp = it->transformed(m);
515
      //Possible point of discontinuity?
516
      ret.append(*temp);
517
      delete temp;
518
    }
12065 fschmid 519
    return ret;
520
  }
521
 
15347 fschmid 522
  Point pointAt(double t) const {
523
    if(empty()) return Point(0,0);
524
    double i, f = modf(t, &i);
525
    if(i == size() && f == 0) { i--; }
526
    assert(i >= 0 && i <= size());
527
    return (*this)[unsigned(i)].pointAt(f);
12065 fschmid 528
  }
529
 
15347 fschmid 530
  double valueAt(double t, Dim2 d) const {
531
    if(empty()) return 0;
532
    double i, f = modf(t, &i);
533
    if(i == size() && f == 0) { i--; }
534
    assert(i >= 0 && i <= size());
535
    return (*this)[unsigned(i)].valueAt(f, d);
12065 fschmid 536
  }
537
 
538
  std::vector<double> roots(double v, Dim2 d) const {
539
    std::vector<double> res;
540
    for(unsigned i = 0; i <= size(); i++) {
541
      std::vector<double> temp = (*this)[i].roots(v, d);
542
      for(unsigned j = 0; j < temp.size(); j++)
543
        res.push_back(temp[j] + i);
544
    }
545
    return res;
546
  }
15347 fschmid 547
 
12065 fschmid 548
  void appendPortionTo(Path &p, double f, double t) const;
549
 
550
  Path portion(double f, double t) const {
551
    Path ret;
552
    ret.close(false);
553
    appendPortionTo(ret, f, t);
554
    return ret;
555
  }
556
  Path portion(Interval i) const { return portion(i.min(), i.max()); }
557
 
558
  Path reverse() const {
15347 fschmid 559
    Path ret;
560
    ret.close(closed_);
561
    for(int i = size() - (closed_ ? 0 : 1); i >= 0; i--) {
562
      //TODO: do we really delete?
563
      Curve *temp = (*this)[i].reverse();
564
      ret.append(*temp);
565
      delete temp;
12065 fschmid 566
    }
567
    return ret;
568
  }
569
 
15347 fschmid 570
  void insert(iterator pos, Curve const &curve) {
571
    Sequence source(1, curve.duplicate());
572
    try {
573
      do_update(pos.impl_, pos.impl_, source.begin(), source.end());
574
    } catch (...) {
575
      delete_range(source.begin(), source.end());
576
      throw;
577
    }
12065 fschmid 578
  }
579
 
15347 fschmid 580
  template <typename Impl>
581
  void insert(iterator pos, BaseIterator<Impl> first, BaseIterator<Impl> last)
12065 fschmid 582
  {
15347 fschmid 583
    Sequence source(DuplicatingIterator<Impl>(first.impl_),
584
                    DuplicatingIterator<Impl>(last.impl_));
585
    try {
586
      do_update(pos.impl_, pos.impl_, source.begin(), source.end());
587
    } catch (...) {
588
      delete_range(source.begin(), source.end());
589
      throw;
590
    }
12065 fschmid 591
  }
592
 
593
  void clear() {
15347 fschmid 594
    do_update(curves_.begin(), curves_.end()-1,
595
              curves_.begin(), curves_.begin());
12065 fschmid 596
  }
597
 
15347 fschmid 598
  void erase(iterator pos) {
599
    do_update(pos.impl_, pos.impl_+1, curves_.begin(), curves_.begin());
12065 fschmid 600
  }
601
 
15347 fschmid 602
  void erase(iterator first, iterator last) {
603
    do_update(first.impl_, last.impl_, curves_.begin(), curves_.begin());
12065 fschmid 604
  }
605
 
15347 fschmid 606
  void replace(iterator replaced, Curve const &curve) {
607
    Sequence source(1, curve.duplicate());
608
    try {
609
      do_update(replaced.impl_, replaced.impl_+1, source.begin(), source.end());
610
    } catch (...) {
611
      delete_range(source.begin(), source.end());
612
      throw;
613
    }
12065 fschmid 614
  }
615
 
15347 fschmid 616
  void replace(iterator first_replaced, iterator last_replaced,
617
               Curve const &curve)
12065 fschmid 618
  {
15347 fschmid 619
    Sequence source(1, curve.duplicate());
620
    try {
621
      do_update(first_replaced.impl_, last_replaced.impl_,
622
                source.begin(), source.end());
623
    } catch (...) {
624
      delete_range(source.begin(), source.end());
625
      throw;
626
    }
12065 fschmid 627
  }
628
 
15347 fschmid 629
  template <typename Impl>
630
  void replace(iterator replaced,
631
               BaseIterator<Impl> first, BaseIterator<Impl> last)
12065 fschmid 632
  {
15347 fschmid 633
    Sequence source(DuplicatingIterator<Impl>(first.impl_),
634
                    DuplicatingIterator<Impl>(last.impl_));
635
    try {
636
      do_update(replaced.impl_, replaced.impl_+1, source.begin(), source.end());
637
    } catch (...) {
638
      delete_range(source.begin(), source.end());
639
      throw;
640
    }
12065 fschmid 641
  }
642
 
15347 fschmid 643
  template <typename Impl>
644
  void replace(iterator first_replaced, iterator last_replaced,
645
               BaseIterator<Impl> first, BaseIterator<Impl> last)
12065 fschmid 646
  {
15347 fschmid 647
    Sequence source(first.impl_, last.impl_);
648
    try {
649
      do_update(first_replaced.impl_, last_replaced.impl_,
650
                source.begin(), source.end());
651
    } catch (...) {
652
      delete_range(source.begin(), source.end());
653
      throw;
654
    }
12065 fschmid 655
  }
656
 
657
  void start(Point p) {
658
    clear();
659
    final_->setPoint(0, p);
660
    final_->setPoint(1, p);
661
  }
662
 
663
  Point initialPoint() const { return (*final_)[1]; }
664
  Point finalPoint() const { return (*final_)[0]; }
665
 
15347 fschmid 666
  void append(Curve const &curve);
667
  void append(D2<SBasis> const &curve);
12065 fschmid 668
 
669
  template <typename CurveType, typename A>
670
  void appendNew(A a) {
15347 fschmid 671
    do_append(new CurveType((*final_)[0], a));
12065 fschmid 672
  }
673
 
674
  template <typename CurveType, typename A, typename B>
675
  void appendNew(A a, B b) {
15347 fschmid 676
    do_append(new CurveType((*final_)[0], a, b));
12065 fschmid 677
  }
678
 
679
  template <typename CurveType, typename A, typename B, typename C>
680
  void appendNew(A a, B b, C c) {
15347 fschmid 681
    do_append(new CurveType((*final_)[0], a, b, c));
12065 fschmid 682
  }
683
 
684
  template <typename CurveType, typename A, typename B, typename C,
685
                                typename D>
686
  void appendNew(A a, B b, C c, D d) {
15347 fschmid 687
    do_append(new CurveType((*final_)[0], a, b, c, d));
12065 fschmid 688
  }
689
 
690
  template <typename CurveType, typename A, typename B, typename C,
691
                                typename D, typename E>
692
  void appendNew(A a, B b, C c, D d, E e) {
15347 fschmid 693
    do_append(new CurveType((*final_)[0], a, b, c, d, e));
12065 fschmid 694
  }
695
 
696
  template <typename CurveType, typename A, typename B, typename C,
697
                                typename D, typename E, typename F>
698
  void appendNew(A a, B b, C c, D d, E e, F f) {
15347 fschmid 699
    do_append(new CurveType((*final_)[0], a, b, c, d, e, f));
12065 fschmid 700
  }
701
 
702
  template <typename CurveType, typename A, typename B, typename C,
703
                                typename D, typename E, typename F,
704
                                typename G>
705
  void appendNew(A a, B b, C c, D d, E e, F f, G g) {
15347 fschmid 706
    do_append(new CurveType((*final_)[0], a, b, c, d, e, f, g));
12065 fschmid 707
  }
708
 
709
  template <typename CurveType, typename A, typename B, typename C,
710
                                typename D, typename E, typename F,
711
                                typename G, typename H>
712
  void appendNew(A a, B b, C c, D d, E e, F f, G g, H h) {
15347 fschmid 713
    do_append(new CurveType((*final_)[0], a, b, c, d, e, f, g, h));
12065 fschmid 714
  }
715
 
716
  template <typename CurveType, typename A, typename B, typename C,
717
                                typename D, typename E, typename F,
718
                                typename G, typename H, typename I>
719
  void appendNew(A a, B b, C c, D d, E e, F f, G g, H h, I i) {
15347 fschmid 720
    do_append(new CurveType((*final_)[0], a, b, c, d, e, f, g, h, i));
12065 fschmid 721
  }
722
 
723
private:
724
  void do_update(Sequence::iterator first_replaced,
725
                 Sequence::iterator last_replaced,
726
                 Sequence::iterator first,
727
                 Sequence::iterator last);
728
 
729
  void do_append(Curve *curve);
730
 
15347 fschmid 731
  void delete_range(Sequence::iterator first, Sequence::iterator last);
732
 
12065 fschmid 733
  void check_continuity(Sequence::iterator first_replaced,
734
                        Sequence::iterator last_replaced,
735
                        Sequence::iterator first,
736
                        Sequence::iterator last);
737
 
15347 fschmid 738
  Sequence curves_;
739
  LineSegment *final_;
12065 fschmid 740
  bool closed_;
15347 fschmid 741
};
12065 fschmid 742
 
743
inline static Piecewise<D2<SBasis> > paths_to_pw(std::vector<Path> paths) {
744
    Piecewise<D2<SBasis> > ret = paths[0].toPwSb();
745
    for(unsigned i = 1; i < paths.size(); i++) {
746
        ret.concat(paths[i].toPwSb());
747
    }
748
    return ret;
749
}
750
 
15347 fschmid 751
/*
752
class PathPortion : public Curve {
753
  Path *source;
754
  double f, t;
755
  boost::optional<Path> result;
756
 
757
  public:
758
  double from() const { return f; }
759
  double to() const { return t; }
760
 
761
  explicit PathPortion(Path *s, double fp, double tp) : source(s), f(fp), t(tp) {}
762
  Curve *duplicate() const { return new PathPortion(*this); }
763
 
764
  Point initialPoint() const { return source->pointAt(f); }
765
  Point finalPoint() const { return source->pointAt(t); }
766
 
767
  Path actualPath() {
768
    if(!result) *result = source->portion(f, t);
769
    return *result;
770
  }
771
 
772
  Rect boundsFast() const { return actualPath().boundsFast; }
773
  Rect boundsExact() const { return actualPath().boundsFast; }
774
  Rect boundsLocal(Interval i) const { throwNotImplemented(); }
775
 
776
  std::vector<double> roots(double v, Dim2 d) const = 0;
777
 
778
  virtual int winding(Point p) const { return root_winding(*this, p); }
779
 
780
  virtual Curve *portion(double f, double t) const = 0;
781
  virtual Curve *reverse() const { return portion(1, 0); }
782
 
783
  virtual Crossings crossingsWith(Curve const & other) const;
784
 
785
  virtual void setInitial(Point v) = 0;
786
  virtual void setFinal(Point v) = 0;
787
 
788
  virtual Curve *transformed(Matrix const &m) const = 0;
789
 
790
  virtual Point pointAt(Coord t) const { return pointAndDerivatives(t, 1).front(); }
791
  virtual Coord valueAt(Coord t, Dim2 d) const { return pointAt(t)[d]; }
792
  virtual std::vector<Point> pointAndDerivatives(Coord t, unsigned n) const = 0;
793
  virtual D2<SBasis> toSBasis() const = 0;
794
 
795
};
796
*/
797
 
15344 fschmid 798
}
12065 fschmid 799
 
800
namespace std {
801
 
802
template <>
803
inline void swap<Geom::Path>(Geom::Path &a, Geom::Path &b)
804
{
805
  a.swap(b);
806
}
807
 
15347 fschmid 808
}
12065 fschmid 809
 
810
#endif // SEEN_GEOM_PATH_H
811
 
812
/*
813
  Local Variables:
814
  mode:c++
815
  c-file-style:"stroustrup"
15347 fschmid 816
  c-file-offsets:((innamespace . 0)(substatement-open . 0))
12065 fschmid 817
  indent-tabs-mode:nil
15347 fschmid 818
  c-brace-offset:0
12065 fschmid 819
  fill-column:99
820
  End:
821
*/
15347 fschmid 822
// vim: filetype=cpp:expandtab:shiftwidth=2:tabstop=8:softtabstop=2 :