三次Bezier曲线的实现方法

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 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 会经过由 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++)

工程目录是: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,

相关文档
最新文档