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、…、Pn,其贝塞尔曲线即


例如 :


如上公式可如下递归表达: 用 
 表示由点 P0、P1、…、Pn 所决定的贝塞尔曲线。则

用平常话来说, 阶贝塞尔曲线之间的插值。

一些关于参数曲线的术语,有

即多项式

又称作 n 阶的伯恩斯坦基底多项式,定义 00 = 1。

点 Pi 称作贝塞尔曲线的控制点。多边形以带有线的贝塞尔点连接而成,起始于 P0 并以 Pn 终止,称作贝塞尔多边形(或控制多边形)。贝塞尔多边形的凸包(convex hull)包含有贝塞尔曲线。

线性贝塞尔曲线函数中的 t 会经过由 P0 至P1 的 B(t) 所描述的曲线。例如当 t=0.25 时,B(t) 即一条由点 P0 至 P1 路径的四分之一处。就像由 0 至 1 的连续tB(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)3P0+3t(1-t)2P1+3t2(1-t)P2+t3P3 
矩阵表示为:
, 
(6-3-2) 
 。 
在(6-3-2)式中,Mn+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<windows.h> 
#include<stdlib.h> 
#include<time.h> 
#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, 
                        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() % 256, 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() % cxClient, rand() % cyClient); 
 
            Pie(hdc, j = rand() % cxClient, k = rand() % cyClient, n = rand() % cxClient, t = rand() % cyClient, rand() % cxClient, rand() % cyClient, 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); 
}

Bezier曲线原理及其代码实现相关推荐

  1. bezier曲线解析与代码(c++)

    前言: 作为rhino重度用户,我对于nurbs建模早有耳闻,但对于何为nurbs却不得其解.最近借上<计算机辅助设计>课程的机会,对此作了一些深入的学习,于是在此记录一下一些课程笔记和课 ...

  2. Bezier曲线原理—动态解释

    Bezier曲线原理 贝塞尔曲线(Bézier curve),又称贝兹曲线或贝济埃曲线,是应用于二维图形应用程序的数学曲线.一般的矢量图形软件通过它来精确画出曲线,贝兹曲线由线段与节点组成,节点是可拖 ...

  3. Bezier曲线原理及实现代码(c++)

    一.原理: 贝塞尔曲线于1962年,由法国工程师皮埃尔·贝塞尔(Pierre Bézier)所广泛发表,他运用贝塞尔曲线来为汽车的主体进行设计.贝塞尔曲线最初由 Paul de Casteljau 于 ...

  4. Bezier曲线原理

    一.原理: 贝塞尔曲线于1962年,由法国工程师皮埃尔·贝塞尔(Pierre Bézier)所广泛发表,他运用贝塞尔曲线来为汽车的主体进行设计.贝塞尔曲线最初由Paul de Casteljau 于1 ...

  5. Bezier曲线切割

    贝塞尔曲线 目标:在unity中展示Bezier曲线. 贝塞尔曲线原理 用代码实现 bezier数学公式 Bezier公式(一般参数公式) 注解: 阶贝兹曲线可如下推断.给定点P0.P1.-.Pn,其 ...

  6. android曲线位移动画,Bezier曲线在Android动画中的应用

    Android动画的开发中,为了达到更加酷炫的效果,常常需要自定义运动轨迹,或者绘制花式复杂的曲线,这正是Bezier曲线大显神通的地方,本文将带你了解Bezier曲线在Android开发中的一些应用 ...

  7. 实验10 Bezier曲线生成

    1.实验目的: 了解曲线的生成原理: 掌握几种常见的曲线生成算法,利用VC+OpenGL实现Bezier曲线生成算法. 2.实验内容: (1)结合示范代码了解曲线生成原理与算法实现,尤其是Bezier ...

  8. 计算机图形学 实验7 《复杂图形绘制-Bezier曲线与Hermite曲线》

    计算机图形学 实验7 <复杂图形绘制-Bezier曲线与Hermite曲线> 一.实验目的 学习样条曲线的绘制. 二.实验内容 1.绘制Bezier曲线: 2.绘制Hermite曲线. 三 ...

  9. Bezier曲线曲面绘制

    知识点: Bezier曲面性质 Bezier曲线简单理解 代码参考:https://blog.csdn.net/wpxu08/article/details/70208395 曲线 #include ...

最新文章

  1. c语言游戏call调用,C语言-植物大战僵尸-刷僵尸call;fps游戏CS-方框透视(矩阵+传统)...
  2. 特斯拉又被挖墙脚:Autopilot总监离职,加入苹果造车团队
  3. 深度学习 tensorflow tf.layers.conv2d_transpose 反卷积 上采样
  4. linux小红帽实验心得,格林童话小红帽读书心得体会5篇
  5. 【收藏】keepalived配置文件解读
  6. 为什么要使用PreparedStatement
  7. 阿里云人脸识别sdk
  8. thinkphp u不加载css,解决ThinkPHP样式无法加载问题(CSS,JS)
  9. Callback Functions Tutorial
  10. 在win10环境中安装xilinx vivado IDE时出现的问题及解决方法
  11. android gradle时间长,Android Studio gradle需要很长时间才能构建
  12. Ehcahe spring
  13. Vue打包时报错:ReferenceError: primordials is not defined
  14. 录像机CIF、D1、720P、960P、1080P分辨率及硬盘所占空间
  15. PHP的常用框架有哪些?
  16. python中的snip用法_腾讯mac截图软件Snip使用教程
  17. 状态分布函数 详细介绍
  18. 是HTML+CSS的学习笔记捏
  19. 单元测试1-为什么需要单元测试
  20. CSS-增加字体和颜色样式

热门文章

  1. 如何用VI创建.txt格式的文件?
  2. down 网卡端口周期性的up_交换机一个端口反复up和down原因?
  3. CNN(卷积神经网络)是什么?(转)
  4. 第一部分:设计模式六大原则解读——什么是接口隔离
  5. Java初学日记七之系统异常类
  6. Neovim:从 Vimscript 到 Lua
  7. 巧用tree命令导出文件目录递归详情
  8. 计算机硬件系统基本的工作原理是,计算机硬件系统基本工作原理-与非网
  9. Python的输入输出(来自菜鸟教程)
  10. JQuery $.ajax 如何捕获异常信息?