00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef LEMON_BEZIER_H
00018 #define LEMON_BEZIER_H
00019
00027
00028 #include<lemon/xy.h>
00029
00030 namespace lemon {
00031
00032 class BezierBase {
00033 public:
00034 typedef xy<double> xy;
00035 protected:
00036 static xy conv(xy x,xy y,double t) {return (1-t)*x+t*y;}
00037 };
00038
00039 class Bezier1 : public BezierBase
00040 {
00041 public:
00042 xy p1,p2;
00043
00044 Bezier1() {}
00045 Bezier1(xy _p1, xy _p2) :p1(_p1), p2(_p2) {}
00046
00047 xy operator()(double t) const
00048 {
00049
00050 return conv(p1,p2,t);
00051 }
00052 Bezier1 before(double t) const
00053 {
00054 return Bezier1(p1,conv(p1,p2,t));
00055 }
00056
00057 Bezier1 after(double t) const
00058 {
00059 return Bezier1(conv(p1,p2,t),p2);
00060 }
00061
00062 Bezier1 revert() const { return Bezier1(p2,p1);}
00063 Bezier1 operator()(double a,double b) const { return before(b).after(a/b); }
00064 xy grad() const { return p2-p1; }
00065 xy norm() const { return rot90(p2-p1); }
00066 xy grad(double) const { return grad(); }
00067 xy norm(double t) const { return rot90(grad(t)); }
00068 };
00069
00070 class Bezier2 : public BezierBase
00071 {
00072 public:
00073 xy p1,p2,p3;
00074
00075 Bezier2() {}
00076 Bezier2(xy _p1, xy _p2, xy _p3) :p1(_p1), p2(_p2), p3(_p3) {}
00077 Bezier2(const Bezier1 &b) : p1(b.p1), p2(conv(b.p1,b.p2,.5)), p3(b.p2) {}
00078 xy operator()(double t) const
00079 {
00080
00081 return ((1-t)*(1-t))*p1+(2*(1-t)*t)*p2+(t*t)*p3;
00082 }
00083 Bezier2 before(double t) const
00084 {
00085 xy q(conv(p1,p2,t));
00086 xy r(conv(p2,p3,t));
00087 return Bezier2(p1,q,conv(q,r,t));
00088 }
00089
00090 Bezier2 after(double t) const
00091 {
00092 xy q(conv(p1,p2,t));
00093 xy r(conv(p2,p3,t));
00094 return Bezier2(conv(q,r,t),r,p3);
00095 }
00096 Bezier2 revert() const { return Bezier2(p3,p2,p1);}
00097 Bezier2 operator()(double a,double b) const { return before(b).after(a/b); }
00098 Bezier1 grad() const { return Bezier1(2.0*(p2-p1),2.0*(p3-p2)); }
00099 Bezier1 norm() const { return Bezier1(2.0*rot90(p2-p1),2.0*rot90(p3-p2)); }
00100 xy grad(double t) const { return grad()(t); }
00101 xy norm(double t) const { return rot90(grad(t)); }
00102 };
00103
00104 class Bezier3 : public BezierBase
00105 {
00106 public:
00107 xy p1,p2,p3,p4;
00108
00109 Bezier3() {}
00110 Bezier3(xy _p1, xy _p2, xy _p3, xy _p4) :p1(_p1), p2(_p2), p3(_p3), p4(_p4) {}
00111 Bezier3(const Bezier1 &b) : p1(b.p1), p2(conv(b.p1,b.p2,1.0/3.0)),
00112 p3(conv(b.p1,b.p2,2.0/3.0)), p4(b.p2) {}
00113 Bezier3(const Bezier2 &b) : p1(b.p1), p2(conv(b.p1,b.p2,2.0/3.0)),
00114 p3(conv(b.p2,b.p3,1.0/3.0)), p4(b.p3) {}
00115
00116 xy operator()(double t) const
00117 {
00118
00119 return ((1-t)*(1-t)*(1-t))*p1+(3*t*(1-t)*(1-t))*p2+
00120 (3*t*t*(1-t))*p3+(t*t*t)*p4;
00121 }
00122 Bezier3 before(double t) const
00123 {
00124 xy p(conv(p1,p2,t));
00125 xy q(conv(p2,p3,t));
00126 xy r(conv(p3,p4,t));
00127 xy a(conv(p,q,t));
00128 xy b(conv(q,r,t));
00129 xy c(conv(a,b,t));
00130 return Bezier3(p1,p,a,c);
00131 }
00132
00133 Bezier3 after(double t) const
00134 {
00135 xy p(conv(p1,p2,t));
00136 xy q(conv(p2,p3,t));
00137 xy r(conv(p3,p4,t));
00138 xy a(conv(p,q,t));
00139 xy b(conv(q,r,t));
00140 xy c(conv(a,b,t));
00141 return Bezier3(c,b,r,p4);
00142 }
00143 Bezier3 revert() const { return Bezier3(p4,p3,p2,p1);}
00144 Bezier3 operator()(double a,double b) const { return before(b).after(a/b); }
00145 Bezier2 grad() const { return Bezier2(3.0*(p2-p1),3.0*(p3-p2),3.0*(p4-p3)); }
00146 Bezier2 norm() const { return Bezier2(3.0*rot90(p2-p1),
00147 3.0*rot90(p3-p2),
00148 3.0*rot90(p4-p3)); }
00149 xy grad(double t) const { return grad()(t); }
00150 xy norm(double t) const { return rot90(grad(t)); }
00151
00152 template<class R,class F,class S,class D>
00153 R recSplit(F &_f,const S &_s,D _d) const
00154 {
00155 const xy a=(p1+p2)/2;
00156 const xy b=(p2+p3)/2;
00157 const xy c=(p3+p4)/2;
00158 const xy d=(a+b)/2;
00159 const xy e=(b+c)/2;
00160 const xy f=(d+e)/2;
00161 R f1=_f(Bezier3(p1,a,d,e),_d);
00162 R f2=_f(Bezier3(e,d,c,p4),_d);
00163 return _s(f1,f2);
00164 }
00165
00166 };
00167
00168 }
00169
00170 #endif // LEMON_BEZIER_H