30 #ifndef SEEN_GEOM_PATH_H
31 #define SEEN_GEOM_PATH_H
36 #include "exception.h"
49 static int root_winding(
Curve const &c,
Point p);
56 virtual Point initialPoint()
const = 0;
57 virtual Point finalPoint()
const = 0;
59 virtual bool isDegenerate()
const = 0;
61 virtual Curve *duplicate()
const = 0;
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); }
68 virtual std::vector<double> roots(
double v, Dim2 d)
const = 0;
70 virtual int winding(
Point p)
const {
return root_winding(*
this, p); }
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;
77 virtual void setInitial(
Point v) = 0;
78 virtual void setFinal(
Point v) = 0;
80 virtual Curve *transformed(
Matrix const &m)
const = 0;
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;
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);
104 double valueAt(
Coord t, Dim2 d)
const {
return inner[d].valueAt(t); }
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]; } }
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); }
113 std::vector<double> roots(
double v, Dim2 d)
const {
return Geom::roots(inner[d] - v); }
115 Curve *portion(
double f,
double t)
const {
116 return new SBasisCurve(Geom::portion(inner, f, t));
123 Curve *derivative()
const {
131 template <
unsigned order>
136 template <
unsigned required_degree>
150 assert_degree<1>(
this);
151 for(
unsigned d = 0; d < 2; d++)
152 inner[d] =
Bezier(c0[d], c1[d]);
156 assert_degree<2>(
this);
157 for(
unsigned d = 0; d < 2; d++)
158 inner[d] =
Bezier(c0[d], c1[d], c2[d]);
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]);
167 unsigned degree()
const {
return order; }
171 Point initialPoint()
const {
return inner.at0(); }
172 Point finalPoint()
const {
return inner.at1(); }
174 bool isDegenerate()
const {
return inner.isConstant(); }
176 void setInitial(
Point v) { setPoint(0, v); }
177 void setFinal(
Point v) { setPoint(1, v); }
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]); }
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);
188 if(deg == 1 && order > 1)
return Rect(bounds_local(Geom::derivative(inner[X]), i),
189 bounds_local(Geom::derivative(inner[Y]), i));
195 int winding(
Point p)
const {
200 roots(
double v, Dim2 d)
const {
201 return (inner[d] - v).roots();
204 void setPoints(std::vector<Point> ps) {
205 for(
unsigned i = 0; i <= order; i++) {
209 std::vector<Point> points()
const {
return bezier_points(inner); }
212 std::pair<Bezier, Bezier > sx = inner[X].subdivide(t), sy = inner[Y].subdivide(t);
218 Curve *portion(
double f,
double t)
const {
219 return new BezierCurve(Geom::portion(inner, f, t));
222 Curve *reverse()
const {
228 std::vector<Point> ps = points();
229 for(
unsigned i = 0; i <= order; i++) ps[i] = ps[i] * m;
234 Curve *derivative()
const {
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];
240 double slope = dy / dx;
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); }
250 double valueAt(
double t, Dim2 d)
const {
return inner[d].valueAt(t); }
252 D2<SBasis> toSBasis()
const {
return inner.toSBasis(); }
256 Coord x[order+1], y[order+1];
257 for(
unsigned i = 0; i <= order; i++) {
258 x[i] = c[i][X]; y[i] = c[i][Y];
276 double x_axis_rotation,
bool large_arc,
277 bool sweep,
Point final)
278 : initial_(initial), rx_(rx), ry_(ry), x_axis_rotation_(x_axis_rotation),
279 large_arc_(large_arc), sweep_(sweep), final_(
final)
284 Point initialPoint()
const {
return initial_; }
285 Point finalPoint()
const {
return final_; }
287 void setInitial(
Point v) { initial_ = v; }
288 void setFinal(
Point v) { final_ = v; }
292 bool isDegenerate()
const {
return toSBasis().isConstant(); }
293 Rect boundsFast()
const;
294 Rect boundsExact()
const;
295 Rect boundsLocal(
Interval i,
unsigned deg)
const;
297 int winding(
Point p)
const {
301 std::vector<double> roots(
double v, Dim2 d)
const;
303 inline std::pair<SVGEllipticalArc, SVGEllipticalArc>
306 a.final_ = b.initial_ = pointAt(t);
307 return std::pair<SVGEllipticalArc, SVGEllipticalArc>(a, b);
311 Curve *portion(
double f,
double t)
const {
313 ret->initial_ = pointAt(f);
314 ret->final_ = pointAt(t);
319 Curve *reverse()
const {
321 ret->initial_ = final_;
322 ret->final_ = initial_;
329 ret->initial_ = initial_ * m;
330 ret->final_ = final_ * m;
334 Curve *derivative()
const { throwNotImplemented(0); }
336 std::vector<Point> pointAndDerivatives(
Coord t,
unsigned n)
const;
344 double x_axis_rotation_;
350 template <
typename IteratorImpl>
352 :
public std::iterator<std::forward_iterator_tag, Curve const>
361 return other.impl_ == impl_;
364 return other.impl_ != impl_;
367 Curve const &operator*()
const {
return **impl_; }
368 Curve const *operator->()
const {
return *impl_; }
388 template <
typename Iterator>
390 :
public std::iterator<std::input_iterator_tag, Curve *>
397 return other.impl_ == impl_;
400 return other.impl_ != impl_;
403 Curve *operator*()
const {
return (*impl_)->duplicate(); }
421 typedef std::vector<Curve *> Sequence;
426 typedef Sequence::size_type size_type;
427 typedef Sequence::difference_type difference_type;
430 : final_(
new LineSegment()), closed_(
false)
432 curves_.push_back(final_);
436 : final_(
new LineSegment()), closed_(other.closed_)
438 curves_.push_back(final_);
439 insert(begin(), other.begin(), other.end());
443 : final_(
new LineSegment(p, p)), closed_(
false)
445 curves_.push_back(final_);
448 template <
typename Impl>
450 : final_(
new LineSegment()), closed_(closed)
452 curves_.push_back(final_);
453 insert(begin(), first, last);
457 delete_range(curves_.begin(), curves_.end()-1);
461 Path &operator=(
Path const &other) {
463 insert(begin(), other.begin(), other.end());
464 close(other.closed_);
468 void swap(
Path &other);
470 Curve const &operator[](
unsigned i)
const {
return *curves_[i]; }
472 iterator begin() {
return curves_.begin(); }
473 iterator end() {
return curves_.end()-1; }
475 Curve const &front()
const {
return *curves_[0]; }
476 Curve const &back()
const {
return *curves_[curves_.size()-2]; }
478 const_iterator begin()
const {
return curves_.begin(); }
479 const_iterator end()
const {
return curves_.end()-1; }
481 const_iterator end_open()
const {
return curves_.end()-1; }
482 const_iterator end_closed()
const {
return curves_.end(); }
483 const_iterator end_default()
const {
484 return ( closed_ ? end_closed() : end_open() );
487 size_type size()
const {
return curves_.size()-1; }
488 size_type max_size()
const {
return curves_.max_size()-1; }
490 bool empty()
const {
return curves_.size() == 1; }
491 bool closed()
const {
return closed_; }
492 void close(
bool closed=
true) { closed_ = closed; }
494 Rect boundsFast()
const;
495 Rect boundsExact()
const;
502 for(const_iterator it = begin(); it != end(); ++it) {
503 if (!it->isDegenerate()) {
504 ret.
push(it->toSBasis(), i++);
512 for(const_iterator it = begin(); it != end(); ++it) {
513 Curve *temp = it->transformed(m);
521 Point pointAt(
double t)
const {
522 if(empty())
return Point(0,0);
523 double i, f = modf(t, &i);
524 if(i == size() && f == 0) { i--; }
525 assert(i >= 0 && i <= size());
526 return (*
this)[unsigned(i)].pointAt(f);
529 double valueAt(
double t, Dim2 d)
const {
530 if(empty())
return 0;
531 double i, f = modf(t, &i);
532 if(i == size() && f == 0) { i--; }
533 assert(i >= 0 && i <= size());
534 return (*
this)[unsigned(i)].valueAt(f, d);
537 std::vector<double> roots(
double v, Dim2 d)
const {
538 std::vector<double> res;
539 for(
unsigned i = 0; i <= size(); i++) {
540 std::vector<double> temp = (*this)[i].roots(v, d);
541 for(
unsigned j = 0; j < temp.size(); j++)
542 res.push_back(temp[j] + i);
547 void appendPortionTo(
Path &p,
double f,
double t)
const;
549 Path portion(
double f,
double t)
const {
552 appendPortionTo(ret, f, t);
555 Path portion(
Interval i)
const {
return portion(i.min(), i.max()); }
557 Path reverse()
const {
560 for(
int i = size() - (closed_ ? 0 : 1); i >= 0; i--) {
562 Curve *temp = (*this)[i].reverse();
569 void insert(iterator pos,
Curve const &curve) {
570 Sequence source(1, curve.duplicate());
572 do_update(pos.impl_, pos.impl_, source.begin(), source.end());
574 delete_range(source.begin(), source.end());
579 template <
typename Impl>
585 do_update(pos.impl_, pos.impl_, source.begin(), source.end());
587 delete_range(source.begin(), source.end());
593 do_update(curves_.begin(), curves_.end()-1,
594 curves_.begin(), curves_.begin());
597 void erase(iterator pos) {
598 do_update(pos.impl_, pos.impl_+1, curves_.begin(), curves_.begin());
601 void erase(iterator first, iterator last) {
602 do_update(first.impl_, last.impl_, curves_.begin(), curves_.begin());
605 void replace(iterator replaced,
Curve const &curve) {
606 Sequence source(1, curve.duplicate());
608 do_update(replaced.impl_, replaced.impl_+1, source.begin(), source.end());
610 delete_range(source.begin(), source.end());
615 void replace(iterator first_replaced, iterator last_replaced,
618 Sequence source(1, curve.duplicate());
620 do_update(first_replaced.impl_, last_replaced.impl_,
621 source.begin(), source.end());
623 delete_range(source.begin(), source.end());
628 template <
typename Impl>
629 void replace(iterator replaced,
635 do_update(replaced.impl_, replaced.impl_+1, source.begin(), source.end());
637 delete_range(source.begin(), source.end());
642 template <
typename Impl>
643 void replace(iterator first_replaced, iterator last_replaced,
646 Sequence source(first.impl_, last.impl_);
648 do_update(first_replaced.impl_, last_replaced.impl_,
649 source.begin(), source.end());
651 delete_range(source.begin(), source.end());
656 void start(
Point p) {
658 final_->setPoint(0, p);
659 final_->setPoint(1, p);
662 Point initialPoint()
const {
return (*final_)[1]; }
663 Point finalPoint()
const {
return (*final_)[0]; }
665 void append(
Curve const &curve);
668 template <
typename CurveType,
typename A>
669 void appendNew(A a) {
670 do_append(
new CurveType((*final_)[0], a));
673 template <
typename CurveType,
typename A,
typename B>
674 void appendNew(A a, B b) {
675 do_append(
new CurveType((*final_)[0], a, b));
678 template <
typename CurveType,
typename A,
typename B,
typename C>
679 void appendNew(A a, B b, C c) {
680 do_append(
new CurveType((*final_)[0], a, b, c));
683 template <
typename CurveType,
typename A,
typename B,
typename C,
685 void appendNew(A a, B b, C c, D d) {
686 do_append(
new CurveType((*final_)[0], a, b, c, d));
689 template <
typename CurveType,
typename A,
typename B,
typename C,
690 typename D,
typename E>
691 void appendNew(A a, B b, C c, D d, E e) {
692 do_append(
new CurveType((*final_)[0], a, b, c, d, e));
695 template <
typename CurveType,
typename A,
typename B,
typename C,
696 typename D,
typename E,
typename F>
697 void appendNew(A a, B b, C c, D d, E e, F f) {
698 do_append(
new CurveType((*final_)[0], a, b, c, d, e, f));
701 template <
typename CurveType,
typename A,
typename B,
typename C,
702 typename D,
typename E,
typename F,
704 void appendNew(A a, B b, C c, D d, E e, F f, G g) {
705 do_append(
new CurveType((*final_)[0], a, b, c, d, e, f, g));
708 template <
typename CurveType,
typename A,
typename B,
typename C,
709 typename D,
typename E,
typename F,
710 typename G,
typename H>
711 void appendNew(A a, B b, C c, D d, E e, F f, G g, H h) {
712 do_append(
new CurveType((*final_)[0], a, b, c, d, e, f, g, h));
715 template <
typename CurveType,
typename A,
typename B,
typename C,
716 typename D,
typename E,
typename F,
717 typename G,
typename H,
typename I>
718 void appendNew(A a, B b, C c, D d, E e, F f, G g, H h, I i) {
719 do_append(
new CurveType((*final_)[0], a, b, c, d, e, f, g, h, i));
723 void do_update(Sequence::iterator first_replaced,
724 Sequence::iterator last_replaced,
725 Sequence::iterator first,
726 Sequence::iterator last);
728 void do_append(
Curve *curve);
730 void delete_range(Sequence::iterator first, Sequence::iterator last);
732 void check_continuity(Sequence::iterator first_replaced,
733 Sequence::iterator last_replaced,
734 Sequence::iterator first,
735 Sequence::iterator last);
744 for(
unsigned i = 1; i < paths.size(); i++) {
745 ret.concat(paths[i].toPwSb());
809 #endif // SEEN_GEOM_PATH_H
double Coord
Definition: coord.h:45
void push(const T &s, double to)
Definition: piecewise.h:86
Definition: piecewise.h:45
Cartesian point.
Definition: point.h:20
Definition: concepts.h:43
Definition: interval.h:56