当前位置:文档之家› 三次Bezier曲线原理及实现代码

三次Bezier曲线原理及实现代码

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 会经过由 P 0 至P 1 的 B(t ) 所描述的曲线。

例如当 t=0.25 时,B(t ) 即一条由点 P 0 至 P 1 路径的四分之一处。

就像由 0 至 1 的连续 t ,B(t ) 描述一条由 P 0 至 P 1 的直线。

为建构二次贝塞尔曲线,可以中介点 Q 0 和 Q 1 作为由 0 至 1 的 t :∙ 由 P 0 至 P 1 的连续点 Q 0,描述一条线性贝塞尔曲线。

∙ 由 P 1 至 P 2 的连续点Q 1,描述一条线性贝塞尔曲线。

∙ 由 Q 0 至 Q 1 的连续点 B(t ),描述一条二次贝塞尔曲线。

∙为建构高阶曲线,便需要相应更多的中介点。

对于三次曲线,可由线性贝塞尔曲线描述的中介点 Q 0、Q 1、Q 2,和由二次曲线描述的点 R 0、R 1 所建构:对于四次曲线,可由线性贝塞尔曲线描述的中介点 Q 0、Q 1、Q 2、Q 3,由二次贝塞尔曲线描述的点 R 0、R 1、R 2,和由三次贝塞尔曲线描述的点 S 0、S 1 所建构:P(t)=(1-t)P0+tP1 ,。

矩阵表示为:,。

P(t)=(1-t)2P0+2t(1-t)P1+t2P2,。

矩阵表示为:,。

P(t)=(1-t)3P0+3t(1-t)2P1+3t2(1-t)P2+t3P3矩阵表示为:,。

(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++)工程目录是:Win32Appvc6.0#include<windows.h>#include<stdlib.h>#include<time.h>#define NUM 10LRESULT 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,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,hInstance,NULL);ShowWindow(hwnd,SW_SHOWMAXIMIZED);UpdateWindow(hwnd);while(GetMessage(&msg,NULL,0,0)){TranslateMessage(&msg);DispatchMessage(&msg);}return msg.wParam;}LRESULT CALLBACK Winproc(HWND hwnd,UINT message, WPARAM wparam,LPARAM lparam){HDC hdc;static POINT pt[NUM];TEXTMETRIC tm;static int cxClient,cyClient;HPEN hpen;int i,j,k,n,t;switch(message){case WM_CREATE:static int cxchar;hdc = GetDC(hwnd);GetTextMetrics(hdc,&tm);cxchar = tm.tmAveCharWidth;ReleaseDC(hwnd,hdc);case WM_SIZE:cxClient = LOWORD(lparam);cyClient = HIWORD(lparam);return 0;case WM_PAINT:hdc = GetDC(hwnd);srand(time(0));Rectangle(hdc,0,0,cxClient,cyClient);for(i=0; i<500; i++){SelectObject(hdc,GetStockObject(WHITE_PEN));PolyBezier(hdc,pt,NUM);for(j=0; j<NUM; j++){pt[j].x = rand()%cxClient;pt[j].y = rand()%cyClient;}hpen =CreatePen(PS_INSIDEFRAME,3,RGB(rand()%256,rand()%25 6,rand()%256));DeleteObject(SelectObject(hdc,hpen));PolyBezier(hdc,pt,NUM);for(k=0; k<50000000;k++);}for(i=0; i<100;i++){Ellipse(hdc,rand()%cxClient,rand()%cyClient,rand()%c xClient,rand()%cyClient);Pie(hdc,j=rand()%cxClient,k=rand()%cyClient,n=rand( )%cxClient,t=rand()%cyClient,rand()%cxClient,rand()%cyC lient,rand()%cxClient,rand()%cyClient) ;}if((n=(n+j)/2)>cxchar*20) n=cxchar*20;SetTextColor(hdc,RGB(rand()%256,rand()%256,rand() %256));TextOut(hdc,n/2,(t+k)/2,TEXT("瑾以此向Pierm Bezier致敬!"),lstrlen(TEXT("瑾以此向Pierm Bezier致敬!")));ReleaseDC(hwnd,hdc);DeleteObject(hpen);ValidateRect(hwnd,NULL);return 0;case WM_DESTROY:PostQuitMessage(0);return 0;}return DefWindowProc(hwnd,message,wparam,lparam); }。

相关主题