完美級的貝塞爾曲線演算法【有完整程式碼】【你應該想不到更好的】
阿新 • • 發佈:2022-02-05
基本原理就是分成2部分和一點,然後遞迴。
比如4點曲線的基本原理:
圖1的藍線=圖3的綠線+曲線點【紅綠交點】+圖3的紅線;
圖3的綠線=>圖1的藍線;
圖3的紅線=>圖1的藍線;
struct xyf; struct xy{ int x; int y; xy(){ } xy(int m){ x=m; y=m; } xy(int x,int y){ this->x=x; this->y=y; } xy(xyf m); xy operator *(xy&m){return xy(x *m.x,y *m.y);} xy operator /(xy&m){return xy(x /m.x,y /m.y);} xy operator %(xy&m){return xy(x %m.x,y %m.y);} xy operator +(xy&m){return xy(x +m.x,y +m.y);} xy operator -(xy&m){return xy(x -m.x,y -m.y);} xy operator <<(xy&m){return xy(x<<m.x,y<<m.y);} xy operator >>(xy&m){return xy(x>>m.x,y>>m.y);} xy operator &(xy&m){return xy(x &m.x,y &m.y);} xy operator |(xy&m){return xy(x |m.x,y |m.y);} xy operator ^(xy&m){return xy(x ^m.x,y ^m.y);} xy operator *=(xy&m){x *=m.x;y *=m.y;return *this;} xy operator /=(xy&m){x /=m.x;y /=m.y;return *this;} xy operator %=(xy&m){x %=m.x;y %=m.y;return *this;} xy operator +=(xy&m){x +=m.x;y +=m.y;return *this;} xy operator -=(xy&m){x -=m.x;y -=m.y;return *this;} xy operator <<=(xy&m){x<<=m.x;y<<=m.y;return *this;} xy operator >>=(xy&m){x>>=m.x;y>>=m.y;return *this;} xy operator &=(xy&m){x &=m.x;y &=m.y;return *this;} xy operator |=(xy&m){x |=m.x;y |=m.y;return *this;} xy operator ^=(xy&m){x ^=m.x;y ^=m.y;return *this;} xy operator *(int m){return xy(x *m,y *m);} xy operator /(int m){return xy(x /m,y /m);} xy operator %(int m){return xy(x %m,y %m);} xy operator +(int m){return xy(x +m,y +m);} xy operator -(int m){return xy(x -m,y -m);} xy operator <<(int m){return xy(x<<m,y<<m);} xy operator >>(int m){return xy(x>>m,y>>m);} xy operator &(int m){return xy(x &m,y &m);} xy operator |(int m){return xy(x |m,y |m);} xy operator ^(int m){return xy(x ^m,y ^m);} xy operator *=(int m){x *=m;y *=m;return *this;} xy operator /=(int m){x /=m;y /=m;return *this;} xy operator %=(int m){x %=m;y %=m;return *this;} xy operator +=(int m){x +=m;y +=m;return *this;} xy operator -=(int m){x -=m;y -=m;return *this;} xy operator <<=(int m){x<<=m;y<<=m;return *this;} xy operator >>=(int m){x>>=m;y>>=m;return *this;} xy operator &=(int m){x &=m;y &=m;return *this;} xy operator |=(int m){x |=m;y |=m;return *this;} xy operator ^=(int m){x ^=m;y ^=m;return *this;} bool operator <(xy&m){return((unsigned(x) <unsigned(m.x))&&(unsigned(y) <unsigned(m.y)));} bool operator >(xy&m){return((unsigned(x) >unsigned(m.x))&&(unsigned(y) >unsigned(m.y)));} bool operator <=(xy&m){return((unsigned(x)<=unsigned(m.x))&&(unsigned(y)<=unsigned(m.y)));} bool operator >=(xy&m){return((unsigned(x)>=unsigned(m.x))&&(unsigned(y)>=unsigned(m.y)));} bool operator ==(xy&m){return((unsigned(x)==unsigned(m.x))&&(unsigned(y)==unsigned(m.y)));} bool operator <(int m){return((unsigned(x) <unsigned(m))&&(unsigned(y) <unsigned(m)));} bool operator >(int m){return((unsigned(x) >unsigned(m))&&(unsigned(y) >unsigned(m)));} bool operator <=(int m){return((unsigned(x)<=unsigned(m))&&(unsigned(y)<=unsigned(m)));} bool operator >=(int m){return((unsigned(x)>=unsigned(m))&&(unsigned(y)>=unsigned(m)));} bool operator ==(int m){return((unsigned(x)==unsigned(m))&&(unsigned(y)==unsigned(m)));} xy operator !(){return xy( !x, !y);} xy operator ~(){return xy( ~x, ~y);} xy operator +(){return xy( +x, +y);} xy operator -(){return xy( -x, -y);} xy get_number(){ xy m=0; if(x>0)m.x=+x;if(x<0)m.x=-x; if(y>0)m.y=+y;if(y<0)m.y=-y; return m; } xy get_flag(){ xy m=0; if(x>0)m.x=+1;if(x<0)m.x=-1; if(y>0)m.y=+1;if(y<0)m.y=-1; return m; } void x_y(){ int v=x;x=y;y=v; } int xx(){return x*x;} int yy(){return y*y;} int xx_yy(){ return (x*x+y*y); } xy operator =(xy&m){ x=m.x; y=m.y; return *this; } xy operator =(int m){ x=m; y=m; return *this; } xy operator ++(int){ xy temp=*this; ++x; ++y; return temp; } xy operator ++(){ x++; y++; return *this; } xy operator --(int){ xy temp=*this; --x; --y; return temp; } xy operator --(){ x--; y--; return *this; } }; struct xyf{ double x; double y; xyf(){ } xyf(double m){ x=m; y=m; } xyf(double x,double y){ this->x=x; this->y=y; } xyf(xy m){ this->x=m.x; this->y=m.y; } xyf operator *(xyf&m){return xyf(x *m.x,y *m.y);} xyf operator /(xyf&m){return xyf(x /m.x,y /m.y);} xyf operator +(xyf&m){return xyf(x +m.x,y +m.y);} xyf operator -(xyf&m){return xyf(x -m.x,y -m.y);} xyf operator *=(xyf&m){x *=m.x;y *=m.y;return *this;} xyf operator /=(xyf&m){x /=m.x;y /=m.y;return *this;} xyf operator +=(xyf&m){x +=m.x;y +=m.y;return *this;} xyf operator -=(xyf&m){x -=m.x;y -=m.y;return *this;} xyf operator *(double m){return xyf(x *m,y *m);} xyf operator /(double m){return xyf(x /m,y /m);} xyf operator +(double m){return xyf(x +m,y +m);} xyf operator -(double m){return xyf(x -m,y -m);} xyf operator *=(double m){x *=m;y *=m;return *this;} xyf operator /=(double m){x /=m;y /=m;return *this;} xyf operator +=(double m){x +=m;y +=m;return *this;} xyf operator -=(double m){x -=m;y -=m;return *this;} xyf get_number(){ xyf m=0; if(x>0)m.x=+x;if(x<0)m.x=-x; if(y>0)m.y=+y;if(y<0)m.y=-y; return m; } xyf get_flag(){ xyf m=0; if(x>0)m.x=+1;if(x<0)m.x=-1; if(y>0)m.y=+1;if(y<0)m.y=-1; return m; } void x_y(){ double v=x;x=y;y=v; } double xx(){return x*x;} double yy(){return y*y;} double xx_yy(){ return (x*x+y*y); } xyf operator =(xy&m){ x=m.x; y=m.y; return *this; } xyf operator =(xyf&m){ x=m.x; y=m.y; return *this; } xyf operator =(double m){ x=m; y=m; return *this; } xyf operator ++(int){ xyf temp=*this; ++x; ++y; return temp; } xyf operator ++(){ x++; y++; return *this; } xyf operator --(int){ xyf temp=*this; --x; --y; return temp; } xyf operator --(){ x--; y--; return *this; } }; xy::xy(xyf m){ x=m.x; y=m.y; } int paint_line(xy r,xy *da){ // float->int (f+0.5) // [-0.5,+0.5)=0 // [+0.5,+1.5)=1 // [+1.5,+2.5)=2 // x*a+b*y=0; // (x+v)*a=x*a+v*a; // (y+v)*a=y*a+v*a; xy n=r.get_number(); xy f=r.get_flag(); xy nn=n*2; xy d=0; xy*db=da; *db++=d; if(n.y<n.x){ int v=n.x; while(d.x!=r.x){ d.x+=f.x; v-=nn.y; if(v<0){ v+=nn.x; d.y+=f.y; } *db++=d; } }else{ int v=n.y; while(d.y!=r.y){ d.y+=f.y; v-=nn.x; if(v<0){ v+=nn.y; d.x+=f.x; } *db++=d; } } return (db-da); } int paint_line(xy a,xy b,xy *da){ int dn=paint_line(b-a,da); for(int i=0;i<dn;i++)da[i]+=a; return dn; } const int curve_max=10; const int curve_bit=16; const int curve_bit_add=1<<(curve_bit-1); xy curve_get(xy m){ m+=curve_bit_add; m>>=curve_bit; return m; } xy*curve_call3(xy s1,xy s2,xy s3,xy*da){ xy y1=(s1+s2)>>1; xy y2=(s2+s3)>>1; xy zz=(y1+y2)>>1; xy z=curve_get(zz); if(z==curve_get(s1))return da; if(z==curve_get(s3))return da; da=curve_call3(s1,y1,zz,da); *da++=z; da=curve_call3(s3,y2,zz,da); return da; } xy*curve_call4(xy s1,xy s2,xy s3,xy s4,xy*da){ xy x1=(s1+s2)>>1; xy x2=(s2+s3)>>1; xy x3=(s3+s4)>>1; xy y1=(x1+x2)>>1; xy y2=(x2+x3)>>1; xy zz=(y1+y2)>>1; xy z=curve_get(zz); if(z==curve_get(s1))return da; if(z==curve_get(s4))return da; da=curve_call4(s1,x1,y1,zz,da); *da++=z; da=curve_call4(s4,x3,y2,zz,da); return da; } xy*curve_call(xy*sa,int sn,xy*da){ xy a[curve_max]; xy b[curve_max]; xy s[curve_max]; for(int i=0;i<sn;i++)s[i]=sa[i]; for(int n=sn,j=0;0<n;n--,j++){ a[j]=s[0]; b[j]=s[n-1]; for(int i=1;i<n;i++)s[i-1]=(s[i-1]+s[i])>>1;; } xy z=curve_get(s[0]); if(z==curve_get(sa[0]))return da; if(z==curve_get(sa[sn-1]))return da; da=curve_call(a,sn,da); *da++=z; da=curve_call(b,sn,da); return da; } int curve(xy*sa__,int sn,xy*da){ if(sn==2)return paint_line(sa__[0],sa__[1],da); if(3<=sn&&sn<=curve_max){}else return 0; xy sa[curve_max]; for(int i=0;i<sn;i++)sa[i]=sa__[i]<<curve_bit; xy*db=da; *db++=curve_get(sa[0]); db=curve_call(sa,sn,db); /* if(0){ }else if(3==sn){db=curve_call3(sa[0],sa[1],sa[2],db); }else if(4==sn){db=curve_call4(sa[0],sa[1],sa[2],sa[3],db); }else return 0; */ *db++=curve_get(sa[sn-1]); return db-da; }