Bezier曲线的定义
Bezier曲线在起点与终点位置与多边形重合。当给定空间n+1个点的位置矢量,则n次Bezier曲线上各点坐标的插值公式为:
C(t)=∑i=0nPiBi,n(t)C(t)=∑i=0nPiBi,n(t)
其中,n此Bernstein基函数为: Bi,n(t)=n!i!(n−i)!ti(1−t)n−iBi,n(t)=n!i!(n−i)!ti(1−t)n−i
Bezier曲线的性质
- 端点性质:曲线在端点处的位置矢量、切矢量、曲率均与特征多边形的相同
- 对称性
- 凸包性。曲线是各点的凸线性组合
- 几何不变性
- 变差缩减性
De Casteliau 算法
Pri(t)=(1−t)Pr−1i(t)+tPr−1i+1(t)Pir(t)=(1−t)Pir−1(t)+tPi+1r−1(t)
算法实现
#include<iostream>
#include<algorithm>
#include<opencv2\core\core.hpp>
#include<opencv2\highgui\highgui.hpp>
#include"MyPoint.h"
#define WIDTH 1000
#define HEIGHT 500
using namespace std;
using namespace cv;
MyPoint DeCasteliau(int degree, const vector<MyPoint>& pv, double t);
int main(){
Mat imageROI = Mat(HEIGHT, WIDTH, CV_8UC3, Scalar(255, 255, 255));
vector<MyPoint> pv;
MyPoint P;
int degree = 0, npoints = 0;
cout << "Please input the number of points of the Bezier Curve:" << endl;
cin >> npoints;
cout << "Please input the degree of the Bezier Curve:" << endl;
cin >> degree;
cout << "Please input the coodinate of the controling points" << endl;
double t = 0, delta;
int i;
int x, y;
delta = 1.0 / npoints;
for (i = 0; i < degree; i++){
cin >> x >> y;
circle(imageROI, cvPoint(x, y), 5, Scalar(0, 0, 0), -1);
pv.push_back(MyPoint(x, y));
}
for (i = 0, t = 0.0; i < npoints; i++){
P = DeCasteliau(degree, pv, t);
imageROI.at<Vec3b>(P.GetY(), P.GetX()) = Vec3b(0, 0, 0);
t += delta;
}
namedWindow("显示结果");
imshow("显示结果", imageROI);
waitKey();
}
MyPoint DeCasteliau(int degree, const vector<MyPoint>& pv,double t){
vector<MyPoint> newpv;
vector<MyPoint>::const_iterator iterForP;
vector<MyPoint>::iterator iterForN;
int r, i;
double t1 = 1.0 - t;
for (iterForP = pv.begin(); iterForP != pv.end(); iterForP++){
newpv.push_back(*iterForP);
}
for (r = 1; r <= newpv.size(); r++){
for (i = 0; i < newpv.size() - r; i++){
newpv[i] = t1*newpv[i] + t*newpv[i + 1];
}
}
return newpv[0];
}
实现效果: