一、实现方案
贝塞尔曲线原理:贝塞尔曲线是计算机图形图像造型的基本工具,是图形造型运用得最多的基本线条之一。它通过控制曲线上的四个点(起始点、终止点以及两个相互分离的中间点)来创造、编辑图形。其中起重要作用的是位于曲线*的控制线。这条线是虚拟的,中间与贝塞尔曲线交叉,两端是控制端点。移动两端的端点时贝塞尔曲线改变曲线的曲率(弯曲的程度);移动中间点(也就是移动虚拟的控制线)时,贝塞尔曲线在起始点和终止点锁定的情况下做均匀移动。注意,贝塞尔曲线上的所有控制点、节点均可编辑。
具体实现通过贝塞尔公式推导:
定义:给定点Po,P..... Pn,则n次贝塞尔曲线由下式给出:
n次贝塞尔曲线的公式可由如下递归表达:
进一步可以得到贝塞尔曲线的递推计算公式:
所以,想要实现三次Bezier曲线的绘制,只需要令n=k,可得公式为:
为了更好的通过计算机来实现此公式,通过相应的转换,可以得到三次Bezier曲线的矩阵,再通过此推导公式从t=0到t=1之间连续绘制100个点即可得到Bezier曲线。
二、代码实现
//坐标点
struct Point
{
double x, y;
};
int fac(int n) {
if (n == 1 || n == 0)
return 1;
else
return n * fac(n - 1);
}
double powi(double base, int n) {
double res = 1;
for (int i = 1; i <= n; ++i)
res *= base;
return res;
}
void DrawBezierCurve(Point* p, int n, CDC* pDC,int color) {
double a, b;
double temp, temp1, temp2, bi;
for (double t = 0.0; t <= 1; t += 0.01) {
a = 0.0; b = 0.0;
for (int i = 0; i <= n; ++i) {
temp = double(fac(n) / fac(i) / fac(n - i));
temp1 = powi(t, i);
temp2 = powi(1 - t, n - i);
bi = temp * temp1 * temp2;
a = a + bi * p[i].x;
b = b + bi * p[i].y;
}
CPen m_newPen, * m_oldPen;
//创建新画笔
m_newPen.CreatePen(PS_SOLID, 2, color);
//将新画笔选入设备上下文,并且保存旧画笔
m_oldPen = pDC->SelectObject(&m_newPen);
if (t == 0) {
pDC->MoveTo(a, b);
}
else {
pDC->LineTo(a, b);
}
pDC->SelectObject(m_oldPen);
}
}
Ondraw代码:
Point p[4] = { {28,5},{30,20},{35.25},{40,5}};
DrawBezierCurve(p,3, pDC,RGB(10,222,55));
Line(pDC, p[0], p[1]);
Line(pDC, p[1], p[2]);
Line(pDC, p[2], p[3]);
三、代码结果