三次Bezier曲线的实现方法
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Bezier曲线原理及实现代码(c++)
一、原理:
贝塞尔曲线于1962年.由法国工程师皮埃尔·贝塞尔(Pierre Bézier)所广泛发表.他运用贝塞尔曲线来为汽车的主体进行设计。贝塞尔曲线最初由Paul de Casteljau于1959年运用de Casteljau 算法开发.以稳定数值的方法求出贝塞尔曲线。
线性贝塞尔曲线
给定点P0、P1.线性贝塞尔曲线只是一条两点之间的直线。这条线由下式给出:
且其等同于线性插值。
二次方贝塞尔曲线的路径由给定点 P0、P1、P2的函数 B(t) 追踪:
。
TrueType字型就运用了以贝塞尔样条组成的二次贝塞尔曲线。
P0、P1、P2、P3四个点在平面或在三维空间中定义了三次方贝塞尔曲线。曲线起始于 P0走向 P1.并从 P2的方向来到 P3。一般不会经过 P1或 P2;这两个点只是在那里提供方向资讯。P0和 P1之间的间距.决定了曲线在转而趋进 P3之前.走向 P2方向的“长度有多长”。
曲线的参数形式为:
。
现代的成象系统.如PostScript、Asymptote和Metafont.运用了以贝塞尔样条组成的三次贝塞尔曲线.用来描绘曲线轮廓。
一般化
P0、P1、…、P n.其贝塞尔曲线即
。
例如:
。
如上公式可如下递归表达:用表示由点 P0、P1、…、P n所决定的贝塞尔曲线。则
用平常话来说. 阶贝塞尔曲线之间的插值。
一些关于参数曲线的术语.有
即多项式
又称作n阶的伯恩斯坦基底多项式.定义 00 = 1。
点 P i称作贝塞尔曲线的控制点。多边形以带有线的贝塞尔点连接而成.起始于 P0并以 P n 终止.称作贝塞尔多边形(或控制多边形)。贝塞尔多边形的凸包(convex hull)包含有贝塞尔曲线。
线性贝塞尔曲线函数中的t 会经过由 P0至P1的 B(t) 所描述的曲线。例如当t=0.25时.B(t) 即一条由点 P0至 P1路径的四分之一处。就像由 0 至 1 的连续t.B(t) 描述一条由 P0至 P1的直线。
为建构二次贝塞尔曲线.可以中介点 Q0和 Q1作为由 0 至 1 的t:
•由 P0至 P1的连续点 Q0.描述一条线性贝塞尔曲线。
•由 P1至 P2的连续点 Q1.描述一条线性贝塞尔曲线。
•由 Q0至 Q1的连续点 B(t).描述一条二次贝塞尔曲线。
•
为建构高阶曲线.便需要相应更多的中介点。对于三次曲线.可由线性贝塞尔曲线描述的中介点 Q0、Q1、Q2.和由二次曲线描述的点 R0、R1所建构:
对于四次曲线.可由线性贝塞尔曲线描述的中介点 Q0、Q1、Q2、Q3.由二次贝塞尔曲线描述的点 R0、R1、R2.和由三次贝塞尔曲线描述的点 S0、S1所建构:
P(t)=(1-t)P0+tP1 ,。
矩阵表示为:
.。
P(t)=(1-t)2P0+2t(1-t)P1+t2P2,。
矩阵表示为:
.。
P(t)=(1-t)3P
0+3t(1-t)2P
1
+3t2(1-t)P
2
+t3P
3
矩阵表示为:
. 。
(6-3-2)
.。
在(6-3-2)式中.M n+1是一个n+1阶矩阵.称为n次Bezier矩阵。
(6-3-3)
。
其中.
利用(6-3-3)式.我们可以得到任意次Bezier矩阵的显式表示.例如4次和5次Bezier 矩阵为:
.
可以证明.n次Bezier矩阵还可以表示为递推的形式:
(6-3-4)
二、算法(c++)
工程目录是:Win32App
vc6.0
#include
#include
#include
#define NUM 10
LRESULT CALLBACK Winproc(HWND,UINT,WPARAM,LPARAM);
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstanc,LPSTR lpCmdLine,int nShowCmd)
{
MSG msg;
static TCHAR szClassName[] = TEXT("::Bezier样条计算公式由法国雷诺汽车公司的工程师Pierm Bezier于六十年代提出");
HWND hwnd;
WNDCLASS wc;
wc.cbClsExtra =0;
wc.cbWndExtra =0;
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.hCursor = LoadCursor(NULL,IDC_ARROW);
wc.hIcon = LoadIcon(NULL,IDI_APPLICATION);
wc.hInstance = hInstance;
wc.lpfnWndProc = Winproc;
wc.lpszClassName = szClassName;
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW|CS_VREDRAW;
if(!RegisterClass(&wc))
{
MessageBox(NULL,TEXT("注册失败"),TEXT("警告框
"),MB_ICONERROR);
return 0;
}
hwnd = CreateWindow(szClassName,szClassName,
WS_OVERLAPPEDWINDOW,