贝塞尔曲线原理:贝塞尔曲线是计算机图形图像造型的基本工具,是图形造型运用得最多的基本线条之一。它通过控制曲线上的四个点(起始点、终止点以及两个相互分离的中间点)来创造、编辑图形。其中起重要作用的是位于曲线中央的控制线。这条线是虚拟的,中间与贝塞尔曲线交叉,两端是控制端点。移动两端的端点时贝塞尔曲线改变曲线的曲率(弯曲的程度);移动中间点(也就是移动虚拟的控制线)时,贝塞尔曲线在起始点和终止点锁定的情况下做均匀移动。注意,贝塞尔曲线上的所有控制点、节点均可编辑。
具体实现通过贝塞尔公式推导:
定义:给定点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]);