VC实现贝塞尔曲线绘制

合集下载

计算机图形学上机实验4_实现Bezier曲线和Bezier曲面的绘制

计算机图形学上机实验4_实现Bezier曲线和Bezier曲面的绘制

昆明理工大学理学院信息与计算科学专业操作性实验报告年级: 10级姓名:刘陈学号: 201011101128 指导教师:胡杰实验课程名称:计算机图形学程序设计开课实验室:理学院机房216实验内容:1.实验/作业题目:用计算机高级语言VC++6.0实现计算机的基本图元绘制2.实验/作业课时:2学时3.实验过程(包括实验环境、实验内容的描述、完成实验要求的知识或技能):实验环境:(1)硬件:每人一台PC机(2)软件:windows OS,VC++6.0或以上版本。

试验内容及步骤:(1)在VC++环境下创建MFC应用程序工程(单文档)(2)编辑菜单资源(3)添加菜单命令消息处理函数(4)添加成员函数(5)编写函数内容试验要求:(1)掌握Bezier曲线、Bezier曲面、及另一个曲面的算法。

(2)实现对Bezier曲线、Bezier曲面、及另一个曲面。

(3)试验中调试、完善所编程序,能正确运行出设计要求结果。

(4)书写试验报告上交。

4.程序结构(程序中的函数调用关系图)5.算法描述、流程图或操作步骤:在lab4iew.cpp文件中添加如下头文件及变量int flag_2=0;int n_change;#define M 30#define PI 3.14159 //圆周率#include "math.h" //数学头文件在lab4iew.h文件中的public内添加变量:int move;int graflag;void Tiso(float p0[3],float x0, float y0, float p[3]);void OnBezierface();在lab4iew.h文件中的protected内添加变量:int n;//控制点数const int N;//控制点数的上限CPoint* a;//控制点存放的数组double result[4][2];在lab4iew.cpp文件中的函数Clab4iew::OnDraw(CDC* pDC)下添加如下代码:int i,j;for(i=0;i<n;i++){pDC->FillSolidRect(a[i].x-2,a[i].y-2,4,4,RGB(255,55,255));}pDC->MoveTo(a[0]);for(j=0;j<n;j++){ pDC->LineT o(a[j]); }if(n<2) return;//如果控制点数少于2,则不用画CPen pen(0,2,RGB(255,0,255)),*p1;p1=pDC->SelectObject(&pen);……在Lab4iew.cpp文件中添加如下的各个消息处理函数及代码:void CLab4View::OnLButtonDown(UINT nFlags, CPoint point){ if(flag_2==0) //flag_2等于0,此时是输入控制点状态{ CClientDC dc(this); //实时输入一个控制点,在屏幕上显示此点dc.FillSolidRect(point.x-2,point.y-2,4,4,RGB(0,0,255));if(n<N){a[n++]=point;} //给控制点数组a[]赋值else {MessageBox("控制点太多!","waring",MB_OK|MB_ICONINFORMATION);}}else if(flag_2==1) //flag_2等于1,此时是修改控制点状态{ int i;for(i=0;i<n;i++) {if((abs(point.x-a[i].x)<10)&&(abs(point.y-a[i].y)<10)) //给定一个范围,如果在范围内,则选中该控制点{ n_change=i; }}CClientDC dc(this); //如果选中该点,则该点的颜色发生变化dc.FillSolidRect(a[n_change].x-2,a[n_change].y-2,4,4,RGB(255,255,0));}CView::OnLButtonDown(nFlags, point);}void CLab4View::OnLButtonUp(UINT nFlags, CPoint point){ if(flag_2==1) {a[n_change]=point; //给变换的点赋值Invalidate(true); //调用OnDraw函数,重新画控制多边形}CView::OnLButtonUp(nFlags, point);}void CLab4View::OnMouseMove(UINT nFlags, CPoint point){ if(flag_2==1) {if(nFlags==MK_LBUTTON){ a[n_change]=point;Invalidate(true); }}CView::OnMouseMove(nFlags, point);}void CLab4View::Ondrawbezier(){ move=0; graflag=1; Invalidate(true); flag_2=1;}void CLab4View::OnRButtonDown(UINT nFlags, CPoint point){ CRect rc; //点右键,刷新屏幕,使控制定点数归零,并且所有开关变量变为初试值GetClientRect(&rc);CClientDC dc(this);dc.Rectangle(0,0,rc.right,rc.bottom); //清屏n=0; //控制点数归零flag_2=0; //开关变量变为初试值CView::OnRButtonDown(nFlags, point);}void CLab4View::OnMove(){ move=1; flag_2=1;CClientDC dc(this);int i=0;while (i<n){ a[i].y=a[i].y+50; i++; }Invalidate(true); }void CLab4View::OnBezierface(){ Invalidate(true);UpdateWindow();CClientDC dc(this);dc.SetTextColor(RGB(0,0,255));dc.TextOut(160,160,"Bezier曲面");CPen pen1,pen2;pen1.CreatePen(PS_SOLID,1,RGB(255,0,0));pen2.CreatePen(PS_SOLID,3,RGB(0,0,255));int a[24][2]={{100,400},{110,300},{130,250},{150,350}, {200,300},{210,280},{250,200},{280,250},{300,320},{300,280},{330,180},{360,250},{400,400},{380,320},{410,200},{480,280}};int i,j;dc.SelectObject(&pen2);for(i=0;i<16;i=i+4){ dc.MoveTo(a[i][0],a[i][1]);for(j=0;j<4;j++){ dc.LineT o(a[i+j][0],a[i+j][1]); }}for(i=0;i<4;i++){ dc.MoveTo(a[i][0],a[i][1]);for(j=0;j<16;j=j+4){ dc.LineT o(a[i+j][0],a[i+j][1]); }dc.SelectObject(&pen2);}double x,y; x=a[0][0]; y=a[0][1]; dc.MoveTo(x,y);dc.SelectObject(&pen1);double u,w;for(u=0;u<1;u=u+0.01){ double U0=-u*u*u+3*u*u-3*u+1;double U1=3*u*u*u-6*u*u+3*u;double U2=-3*u*u*u+3*u*u;double U3=u*u*u;x=U0*a[0][0]+U1*a[4][0]+U2*a[8][0]+U3*a[12][0];y=U0*a[0][1]+U1*a[4][1]+U2*a[8][1]+U3*a[12][1];dc.MoveTo(x,y);for(w=0;w<1;w=w+0.01){ double W0=-w*w*w+3*w*w-3*w+1;double W1=3*w*w*w-6*w*w+3*w;double W2=-3*w*w*w+3*w*w;double W3=w*w*w;x=((U0*a[0][0]+U1*a[4][0]+U2*a[8][0]+U3*a[12][0])*W0+(U0*a[1][0]+U1*a[5][0]+U2*a[9][0]+U3*a[13][0])*W1+(U0*a[2][0]+U1*a[6][0]+U2*a[10][0]+U3*a[14][0])*W2+(U0*a[3][0]+U1*a[7][0]+U2*a[11][0]+U3*a[15][0])*W3);y=((U0*a[0][1]+U1*a[4][1]+U2*a[8][1]+U3*a[12][1])*W0+(U0*a[1][1]+U1*a[5][1]+U2*a[9][1]+U3*a[13][1])*W1+(U0*a[2][1]+U1*a[6][1]+U2*a[10][1]+U3*a[14][1])*W2+(U0*a[3][1]+U1*a[7][1]+U2*a[11][1]+U3*a[15][1])*W3);dc.LineT o(x,y);Sleep(1);}}for(w=0;w<1;w=w+0.01){ double W0=-w*w*w+3*w*w-3*w+1;double W1=3*w*w*w-6*w*w+3*w;double W2=-3*w*w*w+3*w*w;double W3=w*w*w;x=W0*a[0][0]+W1*a[1][0]+W2*a[2][0]+W3*a[3][0];y=W0*a[0][1]+W1*a[1][1]+W2*a[2][1]+W3*a[3][1];dc.MoveTo(x,y);for(u=0;u<1;u=u+0.01){ double U0=-u*u*u+3*u*u-3*u+1;double U1=3*u*u*u-6*u*u+3*u;double U2=-3*u*u*u+3*u*u;double U3=u*u*u;x=((U0*a[0][0]+U1*a[4][0]+U2*a[8][0]+U3*a[12][0])*W0+(U0*a[1][0]+U1*a[5][0]+U2*a[9][0]+U3*a[13][0])*W1+(U0*a[2][0]+U1*a[6][0]+U2*a[10][0]+U3*a[14][0])*W2+(U0*a[3][0]+U1*a[7][0]+U2*a[11][0]+U3*a[15][0])*W3);y=((U0*a[0][1]+U1*a[4][1]+U2*a[8][1]+U3*a[12][1])*W0+(U0*a[1][1]+U1*a[5][1]+U2*a[9][1]+U3*a[13][1])*W1+(U0*a[2][1]+U1*a[6][1]+U2*a[10][1]+U3*a[14][1])*W2。

三次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 的直线。

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

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

Bezier曲线原理及实现代码(c++)Bezier曲线原理及实现代码(c++)2009-06-30 18:50:09| 分类: |字号⼀、原理:贝塞尔曲线于,由⼯程师(Pierre Bézier)所⼴泛发表,他运⽤贝塞尔曲线来为的主体进⾏设计。

贝塞尔曲线最初由于运⽤开发,以的⽅法求出贝塞尔曲线。

线性贝塞尔曲线给定点 P0、P1,线性贝塞尔曲线只是⼀条两点之间的。

这条线由下式给出:且其等同于。

⼆次⽅贝塞尔曲线的路径由给定点 P0、P1、P2的函数 B(t) 追踪:。

字型就运⽤了以组成的⼆次贝塞尔曲线。

P0、P1、P2、P3四个点在平⾯或在三维空间中定义了三次⽅贝塞尔曲线。

曲线起始于 P0⾛向 P1,并从 P2的⽅向来到 P3。

⼀般不会经过 P1或 P2;这两个点只是在那⾥提供⽅向资讯。

P0和 P1之间的间距,决定了曲线在转⽽趋进 P3之前,⾛向 P2⽅向的“长度有多长”。

形式为:。

现代的成象系统,如、和,运⽤了以组成的三次贝塞尔曲线,⽤来描绘曲线轮廓。

P0、P1、…、P n,其贝塞尔曲线即。

例如:。

如上公式可如下递归表达:⽤表⽰由点 P0、P1、…、P 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,描述⼀条线性贝塞尔曲线。

贝塞尔曲线 递归画法 vc++

贝塞尔曲线 递归画法 vc++

贝塞尔曲线递归画法 vc++贝塞尔曲线是一种平滑曲线,它的形状由一系列的控制点决定。

在计算机图形学中,贝塞尔曲线通常用于绘制平滑的曲线和曲面。

贝塞尔曲线的递归画法是通过递归算法来绘制贝塞尔曲线的一种方法,它可以在绘制曲线时实现更加灵活和精细的控制。

在VC++中,我们可以通过递归算法来实现贝塞尔曲线的绘制。

首先,我们需要了解贝塞尔曲线的数学原理和算法。

贝塞尔曲线由一系列的控制点以及一个参数t决定,通过调整参数t的值,我们可以得到曲线上不同位置的点。

贝塞尔曲线的递归画法可以通过分割曲线的方式来实现。

我们可以将一条贝塞尔曲线分割成两部分,然后再分别递归地绘制每一部分,直到曲线足够平滑为止。

在VC++中,我们可以使用C++语言来实现贝塞尔曲线的递归画法。

首先,我们需要定义一个表示2D点的结构体,用来存储曲线上的点的坐标。

然后,我们需要实现一个递归绘制函数,这个函数接受一组控制点和绘制的精度作为参数,然后递归地绘制曲线直到达到指定的精度为止。

下面是一个简单的示例代码,用来实现贝塞尔曲线的递归画法:```cpp#include <iostream>#include <vector>//定义一个表示2D点的结构体struct Point{float x;float y;};//定义一个递归绘制贝塞尔曲线的函数void drawBezierCurve(std::vector<Point>& controlPoints, float t, int depth){if (depth == 0){//绘制曲线上的点//这里可以使用画图的API来实现}else{std::vector<Point> newPoints;for (int i = 0; i < controlPoints.size() - 1; i++){//根据贝塞尔曲线的递推公式计算新的控制点Point newPoint;newPoint.x = controlPoints[i].x + t * (controlPoints[i + 1].x - controlPoints[i].x);newPoint.y = controlPoints[i].y + t * (controlPoints[i + 1].y - controlPoints[i].y);newPoints.push_back(newPoint);}//递归调用自己drawBezierCurve(newPoints, t, depth - 1);}}int main(){//定义一组控制点std::vector<Point> controlPoints = { {100, 100}, {200, 300}, {400, 200}, {500, 400} };//设置绘制精度int depth = 5;//设置参数t的步长float step = 0.01;//循环调用绘制函数绘制曲线for (float t = 0; t <= 1; t += step){drawBezierCurve(controlPoints, t, depth);}return 0;}```在上面的示例代码中,我们定义了一个表示2D点的结构体Point,然后实现了一个递归绘制贝塞尔曲线的函数drawBezierCurve。

Bezier 曲线绘制实验文档

Bezier 曲线绘制实验文档

Bezier 曲线绘制实验文档
2005.10
一、实验目的
编程实现中点分割法绘制Bezier曲线。

二、实现功能
实验程序通过OpenGL实现,可以通过鼠标单击左键绘制Bezier控制点,单击右键结束控制点绘制并显示Bezier曲线。

单击控制点可以选择控制点,这个时候可以通过拖拽移动控制点,同时Bezier曲线的变化也将反应;按键盘上的d可以删除控制点,i可以在这个控制点和下一个控制点的中点位置增加一个新的控制点。

按c可以清除所有内容以重新绘制。

通过上下键可以增加或者缩小阈值。

三、程序实现
1、Bezier曲线绘制算法
函数calBezier通过中点分割法绘制Bezier曲线。

利用递归的方法实现,calPiece是递归子函数。

算法伪码描述如下:
考虑到最后需要求出2n-1个控制点,因此预先将n个控制点间隔排列放到大小为2n-1的数组中。

之后对于每一层次的求解,将两个控制点的中点求出来的结果放到这两个控制点所在数组序号中间的位置即可。

如下表所示(4个控制点)。

表中红色的内容为每一个循环中需要计算的内容,使用其上一行中序号在前一位和后一位的控制点的中点。

最后结果前4项就是第一段Bezier曲线的控制点,后4项就是第二段Bezier曲线的控制点。

3、OpenGL函数
四、实验结果
在VS2003+WinXP平台下实现了程序。

c++ 贝尔曲线计算模拟两点坐标间的曲线移动轨迹

c++ 贝尔曲线计算模拟两点坐标间的曲线移动轨迹

c++ 贝尔曲线计算模拟两点坐标间的曲线移动轨迹文章标题:深度解析C++中贝尔曲线计算模拟两点坐标间的曲线移动轨迹在现代计算机科学中,C++语言被广泛应用于各种领域,包括图形学和计算机图形学。

其中,贝尔曲线(Bézier curve)是一种常用的数学工具,用于在计算机图形学中模拟两点坐标间的曲线移动轨迹。

本文将从C++语言的角度深入探讨贝尔曲线的计算模拟,旨在帮助读者全面理解和应用贝尔曲线在计算机图形学中的实际应用。

一、贝尔曲线简介在计算机图形学中,贝尔曲线是由一系列控制点和一组特定的数组算法所生成的曲线。

这些控制点决定了贝尔曲线的形状,而贝尔曲线的算法则确定了曲线的平滑度和变化规律。

贝尔曲线广泛用于计算机图形学中的曲线绘制、动画效果和路径规划等方面。

在实际的C++编程中,我们可以通过实现贝尔曲线算法来模拟两点之间的曲线移动轨迹,为计算机图形学和动画效果的实现提供强大的支持。

二、C++中的贝尔曲线计算模拟在C++编程中实现贝尔曲线算法需要考虑诸多因素,包括控制点的设置、贝尔曲线方程的推导和递归求解等。

我们需要确定两个端点和若干个控制点,它们将决定贝尔曲线的形状和路径。

我们可以使用贝尔曲线的递推公式来计算曲线上的点,从而实现曲线的绘制和移动效果。

在C++中,我们可以通过自定义函数或类来实现贝尔曲线算法,并结合图形库或动画库来展现计算结果。

三、C++中贝尔曲线的应用实例为了更具体地说明C++中贝尔曲线的应用,我们可以以一个实际的案例来展示其在计算机图形学中的效果。

假设我们要实现一个动态的曲线路径规划系统,其中涉及到飞机、汽车或无人机的路径模拟。

我们可以利用C++编程语言中的贝尔曲线算法来计算和模拟这些交通工具之间的曲线移动轨迹,从而实现更加真实和生动的动画效果。

四、个人观点和总结通过本文的讨论,我们可以看到C++语言在贝尔曲线计算模拟中的重要作用和实际应用。

贝尔曲线不仅可以用于计算机图形学中的动画效果,还可以应用于路径规划、数据可视化和工程设计等领域。

如何在VC++6.0下实现贝济埃曲线的绘制

如何在VC++6.0下实现贝济埃曲线的绘制
CP n o d e ; e l p n
C e : Viw On But n w n( Fa s on ) L to Do n lg ,p it : } vi odCDrw B z iw: a e Ve :On ut n w n UI Tn lg , on RB to Do ( N Fa s CP it p it on ) (
f F e ̄N w菜 单 ,单 击 Po c 标 签 ,选 择 MF pWi r i- e l r et j CA p z d a ee , 输 人 程 名 Da B z 在 第 ~ 步 中 选 择 Snl D e— x] rw e。 i e ou g m n, 他 各 步 都 用 默 认 设 置 ,最 后 单 击 f s, 成 工 程 的 建 et其 i h完 n
O L ut D w ( 、O R u o D w ( 、O M ue v ( 、 O R n B t n o n ) n B t n o n ) n o sMo e ) o t n— Btn p ) ut U ( 。 o
刻绘制出 一 贝济埃曲线。如 果想调整该曲线 ,只要对准 贝济 条
埃 曲 线 的 4 折 点 中 的 一个 ,按 F鼠标 右 键 ,拖 动 鼠标 到需 要 个
的位 置 ,贝 济 埃 曲 线 亦 随 着 移 动 ,直 到 满 意 为 止 。 下 面 介 绍
V C++下 绘 制 能移 动 的 贝 济埃 曲线 的步 骤 :
步骤 1 启 动 V . c+ +60 . .生 成 名 为 Da B z的 工 程 。 选 rw e
步 骤 6 给 O L ut D w ( 、 O R u oD w ( 、 0 — . n B l n o n ) n B tn o n ) o t n M ue v( 、 O R ut U (函 数 中分 别 添 加 代码 如下 : osMoe ) n B t n p ) o

C语言代码,Bezier三次曲线

C语言代码,Bezier三次曲线
y=(int)(yt);
lineto(x,y);
}
}
void main()
{
static double p[4][2]={50,400,140,20,400,40,635,420};
const NO=3;
int i;
int driver=DETECT,mode;
initgraph(&driver,&mode,"C://tools/tc2.0");//初始化图形系统
Bezier三次曲线实验报告
一:实验目的
用C语言实现Bezier三次曲线原理的划线
二:实验环境
VC6.0
三:实验人数
一人
四:实验内容
Bezier曲线生成的原理和步骤都在程序上给了注释
五:实验步骤
#include <stdio.h>
#include <graphiห้องสมุดไป่ตู้s.h>
#include <conio.h>
//该方法为Bezier三阶的曲线原理
void bezier_3(int color, double p[4][2])
{
double t,t1,t2,xt,yt;
int rate=200,x,y;
setcolor(color);
moveto(p[0][0],p[0][1]);
for (t=0;t<=1;t+=1.0/rate)
bezier_3(LIGHTRED,p);//调用函数,并传递实参颜色、坐标
getch();
closegraph();
}
六:实验问题及解决
用到了很多C语言库自带的函数,通过,进行了学习;如果大家在编译的时候没有#include <graphics.h>请大家安装一个文件
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

VC实现贝塞尔曲线绘制
<a rel='nofollow' onclick="doyoo.util.openChat();return false;"
href="#">
摘要:本文主要通过对Bezier曲线的几何图形的进一步理解,探讨其具体的控制方法,结合具体绘制实际分析理论描述对控制点计算理解的偏差,统一了认识;结合曲线绘制函数PolyBezier()具体的要求,实现VC环境下简单的曲线绘制方法研究。

关键词:贝塞尔曲线;PolyBezier;曲线连续性
1贝塞尔曲线描述
贝赛尔曲线的每一个顶点都有两个控制点,用于控制在该顶点两侧的曲线的弧度。

所以本函数的顶点数组的记录方式是:控制点+顶点+控制点+控制点+顶点+控制点+……。

所以两个顶点之间的曲线是由两个顶点以及两个顶
点之间的控制点来决定的。

一条贝塞尔样条由4个定义点定义:两个端点和两个控制点。

2曲线的绘制方法
2.1PolyBezier函数
PolyBezier函数用于画贝赛尔样条曲线,原型:BOOL PolyBezier(HDC,hdc,CONST POINT *lppt,DWORD cPoints);参数:hdc:指定的设备环境句柄。

Lppt:POINT结构数组的指针,包括了样条端点和控制点的坐标、其顺序是起点的坐标、起点的控制点的坐标、终点的控制点的坐标和终点的坐标。

cPoints:指明数组中的点的个数。

本文中绘制曲线主要用到这个函数。

2.2一阶连续性
图1所示为一段Bezier曲线经过p0、p1两个端点,要绘制经过它们的曲线需要再确定k1、K2两个控制点,这条曲线最终是由p0、k1、k2、p1四个点决定。

图2为经过p0、p1(p2)、p3的一段连续曲线,可以看出,它是由p0-p1及p2-p3两段曲线组成,连续的贝塞尔曲线会把前一个终止点当作起始点:即p1=p2。

要绘制如图2所示曲线,关键在于确定k0、k1、k2、k3四个控制点方法,一般是根据两段曲线连续(即一阶连续性:两个相邻曲线段在交点处有相同的一阶导数)条件来得出。

总的来说,就是k0p0 连线即为曲线在p0处切线,k1p1连
线为p1处切线,k24p2为p2处切线,k3p3为p3处切线,两段曲线连续必然要求k1p1与k2p2在一条线上。

端点处可令其倒数为0,即可算得控制点。

如此在cPoints结构中会顺序存储p0,k0,k1,p1 (p2),k2,k3,p3七个点,调用PolyBezier
函数完成绘制曲线。

上面简单描述了包含在贝塞尔多边形内的贝塞尔曲线
的控制点的推算。

接下来我们以绘制经过固定点形成的多边形基础上理解经过其顶点的相似曲线(多边形的外接曲线)。

根据贝塞尔曲线的定义及控制方法,多边形的顶点即为曲线的端点,关键还是如何理解控制点位置的确定和计算方法,使其既满足曲线的绘制需求又能较好的切合多边形的外沿(图4)。

Bezier曲线Bezier曲线
图3所示为用鼠标选取p0,p1,p2三个点,通过上面的方法绘制的Bezier曲线。

比较图2和图3,都是绘制经过p0、p1、p2三个点的曲线,图3相比图2少2个控制点,实际上是一样的,起点控制点和终点控制点都和各自的起始端点是重合一致的。

如此在cPoints 结构中会顺序存储
p0,p0,k01,p1,k1,p2,p2七个点,把这几个点连接起来就是这条曲线的贝塞尔多边形,代入PolyBezier函数也就满足了画Bezier曲线的条件。

3程序关键代码
程序中定义了一个函数qulv()用来求得控制点,针对图3主要是求得两个控制点k0,k1,尔后得到顺序存储
p0,k0,k01,p1,k1,k12,p2的cPoints结构;绘制出相应的曲线。

如果是针对如图4具有更多端点的图形依此方法重新计算更新lppt结构数据。

void CShape::qulv(int xx1, int xx2, int xx3, int yy1, int yy2, int yy3)
{ //根据曲线一阶连续性条件
//输入三个已知经过的点的横、纵坐标;输出两个控制点的坐标(xz,yz),(xy,yy)
double d12=0.0, d23=0, s=0, w=0, k=0;
d12=0.25*sqrt((xx2-xx1)*(xx2-xx1)+(yy2- y1)*(yy2-yy1));
d23=0.25*sqrt((xx3-xx2)*(xx3-xx2)+(yy3-yy2)*(yy3-yy2));
if(xx3>xx1)s=1;else s=-1;
if(yy3>yy1)w=1; else w=-1;
if(xx3==xx1)
{
xz=xx2;yz=yy2-w * d12;
xy=xx2;yy=yy2+w * d23;
}
else
{
k=(yy3-yy1)/(xx3-xx1);
xz= float(xx2)-s*(d12/sqrt(1+k*k));
yz=float(yy2)-s*(k*d12/sqrt(1+k*k));
xy=float(xx2)+s*(d23/sqrt(1+k*k));
yy=float(yy2)+s*(k*d23/sqrt(1+k*k));
}
}
4总结
Bezier 曲线是计算机图形学中最基本、最重要的内容。

在实际应用中, 可以进一步研究曲线的拼接方法、连续性、拟合等,比较它与其它B样条曲线、双曲线等的区别,进一步发掘它的实用价值并推广到曲面的绘制、拼接研究。

参考文献:
[1] 施法中.计算机辅助几何设计与非均匀有理B 样条[M].北京:北京航空大学出版社,1994.
[2] 严兰兰,宋来忠,李军成.有理Bezier曲线的拼接[J].三峡大学学报(自然科学版),2005,27(5):469-471.
注:“本文中所涉及到的图表、公式、注解等请以PDF 格式阅读”。

相关文档
最新文档