贝塞尔曲线 已知4点和线上的一点x,求y
已知4个点pt[0],pt[1],pt[2],pt[3],和在线上的一点的x,求对应的y。
我的方法是创建一个大画布,用PolyBezier画好曲线后,在x这一列判断是否有点,以求得y。
PolyBezier只能画出曲线,效率太低。
求整个函数代码。
[解决办法]
代码如下:
/*************
* pDC 设备
* flArrayx 组成点x坐标序列
* flArrayy 组成点y坐标序列
**************/
int deCasteljau(CDC *pDC,CArray<float,float>& flArrayx,CArray<float,float>& flArrayy)
{
if(flArrayx.GetSize()!=flArrayy.GetSize())
return 0;
float *pflX,*pflY;
float flTempx,flTempy,flU;//flu-------u参数(和上面t表示意思相同)
int i,n,j;
n=flArrayx.GetSize();
if(n<2) return 0;
pflX=new float[n];
pflY=new float[n];
flTempx=flArrayx.GetAt(0);
flTempy=flArrayy.GetAt(0);
for(i=0;i<n;i++){
pflX[i]=flArrayx.GetAt(i);
pflY[i]=flArrayy.GetAt(i);
}
for(flU=0;flU<=1;flU+=0.05/n){
for(i=1;i<n;i++){
for(j=0;j<n-i;j++){
pflX[j]=(1-flU)*pflX[j]+flU*pflX[j+1];
pflY[j]=(1-flU)*pflY[j]+flU*pflY[j+1];
}
}
pDC->MoveTo(flTempx,flTempy);
pDC->LineTo(pflX[0],pflY[0]);
flTempx=pflX[0];
flTempy=pflY[0];
}
delete[] pflX;
delete[] pflY;
return 1;
}
[解决办法]
double NTBezierFunc(const double ps[4], const double targ, double t) //targ为目标值{ return (1.0-t) * (1.0-t) * (1.0-t) * ps[0] + 3 * (1.0-t) * (1.0-t) * t * ps[1] + 3 * (1.0-t) * t * t * ps[2] + t * t * t * ps[3] - targ;}double DeltaNTBezierFunc(const double ps[4], const double targ, double t) //导数函数,如果你数学好的话自己求导一下吧~~{ double dt=1e-8; return (NTBezierFunc(ps,targ,t)-NTBezierFunc(ps,targ,t-dt))/dt;}void __fastcall TForm1::btnNTClick(TObject *Sender){ //假设四个点 double x[4] = {0,0,200,200}; double y[4] = {50,0,100,50}; //假设已知x为70 double t=0.5; //设置t的初值 int i; for(i=0;i<1000;i++) { t=t-NTBezierFunc(x, 70, t)/DeltaNTBezierFunc(x, 70, t ); if(IsZero(NTBezierFunc(x, 70, t),1e-5)) break; } //用求出的t来算出对应的y值 double Y = NTBezierFunc(y, 0, t);}