计算机图形学实验4-----Hermite Bezier B样条三种曲线的绘制
bezier曲线或b样条曲线的绘制
淮阴工学院计算机科学系实验报告书课程名:《计算机图形学》题目:实验4 BEZIER曲线或B样条曲线的绘制班级:学号:姓名:评语:成绩:指导教师:批阅时间:年月日1、实验内容或题目编程实现三次BEZIER或B样条曲线的绘制。
2、实验目的与要求(1) 通过实验,进一步理解和掌握生成BEZIER或B样条曲线的算法;(2) 掌握BEZIER或B样条曲线的基本生成过程;(3) 通过编程,会在TC环境下编程实现三次BEZIER或B样条曲线的绘制。
3、实验步骤与源程序错误!未找到引用源。
实验步骤1、算法、原理清晰,有详细的设计步骤;2、依据算法、步骤或程序流程图,用C语言编写源程序;3、编辑源程序并进行调试;4、进行特殊模式的运行测试,并结合情况进行调整;5、对运行结果进行保存与分析;6、打印源程序或把源程序以文件的形式提交;7、按格式书写实验报告。
错误!未找到引用源。
源代码#include "graphics.h"float px[4]={ 50,80,120,140 };float py[4]={100,230,230,160};void Bezier(){float a0,a1,a2,a3,b0,b1,b2,b3;int k,x,y;float i,t,n=4;setcolor(15);for(k=0;k<3;k++){moveto(px[k],py[k]);lineto(px[k+1],py[k+1]);}setcolor(4);a0=px[0];a1=-3*px[0]+3*px[1];a2=3*px[0]-6*px[1]+3*px[2];a3=-px[0]+3*px[1]-3*px[2]+px[3];b0=py[0];b1=-3*py[0]+3*py[1];b2=3*py[0]-6*py[1]+3*py[2];b3=-py[0]+3*py[1]-3*py[k+2]+py[3];for(i=0;i<n;i+=0.001){t=i;x=a0+a1*t+a2*t*t+a3*t*t*t;y=b0+b1*t+b2*t*t+b3*t*t*t;if(i==0)moveto(x,y);lineto(x,y);}}void main(){int driver,mode;driver=DETECT;initgraph(&driver,&mode,"..\\bgi");Bezier();}4、测试数据与实验结果5、结果分析与实验体会通过这次实验,我初步熟悉了turboc 的运行环境。
计算机图形学上机实验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。
江苏大学计算机图形学第二次实验报告曲线拟合
江苏大学-计算机图形学第二次实验报告-曲线拟合————————————————————————————————作者: ————————————————————————————————日期:ﻩ计算机科学与通信工程学院实验报告课程计算机图形学实验题目实验二:曲线拟合学生姓名学号专业班级指导教师日期ﻬ成绩评定表评价内容具体内容权重得分论证分析方案论证与综合分析的正确、合理性20%算法设计算法描述的正确性与可读性20%编码实现源代码正确性与可读性30%程序书写规范标识符定义规范,程序书写风格规范20%报告质量报告清晰,提交准时10%总分指导教师签名1. 实验内容1. 绘制三次Bezier曲线(1)给定四个已知点P1—P4,以此作为控制顶点绘制一段三次Bezier曲线。
(2)给定四个已知点P1—P4,以此作为曲线上的点绘制一段三次Bezier曲线。
2.绘制三次B样条曲线给定六个已知点P1—P6,以此作为控制顶点绘制一条三次B样条曲线。
2.实验环境Windows xpVs 20083. 问题分析Bezier曲线通过一组多边折线的各顶点唯一的定义出来。
在多边折线的各顶点中,只有第一点和最后一点在曲线上,其余的顶点则用来定义曲线的导数,阶次和形状。
三次Bezieer曲线经过首、末两个控制点,且与特征多边形的首、末两条边相切。
因此在给定四个控制点的情况下,可以根据线性贝塞尔曲线描述的中介点 Q0、Q1、Q2,和由二次曲线描述的点 R0、R1 所建构。
也可以在给定四个线上点的情况下根据公式计算出曲线。
总之,只要获得了四个控制点的坐标,便可以通过编程来绘制出曲线。
对于给出了四个曲线上点的曲线,由于控制点的坐标位于曲线上,而且在相交处两曲线的切平面重合,曲率相等。
可以据此来绘制图形。
B 样条曲线是Bezier 曲线的拓广,它是用B 样条基函数代替了Bezier 曲线表达式中的Bernst ain 基函数。
在空间给定n+1个点的位置向量Pi (i=0,1,2,……n, n>=k),则称参数曲线,0()()ni i k i Q t t N P ==∑ (0≤t≤1)为k 阶(或k-1次)的B 样条曲线。
hermite曲线与bezier曲线转换
hermite曲线与bezier曲线转换引言:Hermite曲线和Bezier曲线是计算机图形学中常用的两种曲线表示方法。
它们可以用于生成平滑的曲线,广泛应用于计算机辅助设计、动画和游戏开发等领域。
本文将详细介绍Hermite曲线和Bezier曲线的基本概念、特点以及它们之间的转换方法。
正文:1. Hermite曲线1.1 概念和特点Hermite曲线是由法国数学家Charles Hermite于1858年提出的一种参数曲线表示方法。
它通过给定曲线上的两个端点和两个控制向量,可以生成一条平滑的曲线。
其中,端点确定了曲线的起点和终点,而控制向量则决定了曲线在起点和终点处的切线方向。
1.2 基本公式Hermite曲线的表示公式如下:P(t) = (2t^3 - 3t^2 + 1)P0 + (t^3 - 2t^2 + t)M0 + (-2t^3 + 3t^2)P1 + (t^3 - t^2)M1其中,P(t)表示曲线上的点,t为参数值,P0和P1为端点,M0和M1为控制向量。
1.3 应用场景Hermite曲线广泛应用于计算机图形学中的形状设计和动画制作。
它可以用于创建平滑的曲线路径,用于物体的运动轨迹、摄像机的运动路径等。
2. Bezier曲线2.1 概念和特点Bezier曲线是由法国工程师Pierre Bezier于1962年提出的一种参数曲线表示方法。
它通过给定曲线上的若干个控制点,可以生成一条平滑的曲线。
Bezier曲线的特点是可以通过调整控制点的位置来改变曲线的形状。
2.2 基本公式Bezier曲线的表示公式如下:P(t) = ∑(i=0 to n) (Bi(t) * Pi)其中,P(t)表示曲线上的点,t为参数值,n为控制点的数量,Bi(t)为Bezier基函数,Pi为控制点。
2.3 应用场景Bezier曲线广泛应用于计算机图形学中的形状设计和曲线插值。
它可以用于创建平滑的曲线路径,用于绘制二维图形、字体设计等。
课件 计算机图形学 贝塞尔曲线及B样条
n
p(t) pi Bi,n (t)
(0 t 1)
i0
p(t) (1 t)3 p0 3t(1 t)2 p1 3t 2 (1 t) p2 t3 p3
其中混合函数分别为:
B0,3 = 1- 3t + 3t2 - t3 =
B1,3 = 3t - 6t2 + 3t3 =
B2,3 = 3t2 - 3t3 =
(2)通过控制点即顶点直观而方便地调整曲线的形状, (3)仅通过起始点和终止点,而不通过其它的型值点。
三 贝塞尔曲线举例 曲线仅通过起始点和终止点,而不通过其它的型值点。
四 贝塞尔曲线的性质:
1 该曲线由一组多边形折线的多个顶点唯一地定义出来。
多边形折线又称特征多边形,顶点又称为控制点。
2 在多边折线的各个顶点中,只有第1点和最后1点在曲线上。
1 n!
nk j0
(1)
j
j (t n k j)n (0 t 1, k 0,1, n)
n1
P’(0) B2
2 例:n=3,m=1,
B1
P’(1)
表示有5个顶点, 能画出两段3次曲线
B02
B3
B0
P’’(0) P’’(1)
B4
3 n次B样条曲线
连接全部曲线段所组成的整条曲线称为n次B样条曲线。
j 0
j (t 2 j)2 1 (t 1)2
3
2
F1,2 (t)
1 2
(2t
2
2t
1)
t F2,2 (t)
1 2
2
因此,二次 B 样条曲线的分段表达式可以写成如下的形式:
Pi (t) F0,2 (t)Pi F1,2 (t)Pi1 F2,2 (t)Pi2
Bezier曲线和样条曲线的生成算法
计算机图形学实验报告实验名称 Bezier曲线和样条曲线的生成算法评分实验日期年月日指导教师姓名专业班级学号一、实验目的1、复习Bezier曲线和B样条曲线的参数表示法。
2、编程实现用二次Bezier曲线绘制。
3、编程实现用三次Bezier曲线绘制和分段光滑Bezier曲线图形的绘制。
4、用三次B样条函数绘制曲线。
二、实验要求1、编程实现在屏幕上绘制出两次Bezie曲线的几何图形和特征多边形图形,对于直线和曲线设置不同的线形和颜色。
2、现在屏幕上绘制出三次Bezie曲线的几何图形和特征多边形图形,对于直线和曲线设置不同的线形和颜色。
1、编程实现用分段三次Bezier曲线绘制光滑Bezier曲线图形。
1、编程实现在屏幕上绘制出三次B样条函数绘制曲线。
2、编程实现在屏幕上绘制出光滑连接的三次B样条曲线。
三、关键算法及实现原理1、二次Bezier曲线的计算公式为:P(t)=(P0-2P1+P2)t2+(-2P0+2P1)t+P0X(t)=(X0-2X1+X2)t2+(-2X0+2X1)t+X0Y(t)=(Y0-2Y1+Y2)t2+(-2Y0+2Y1)t+Y0其中P0、P1、P2为三个已知的点,坐标分别为(X0、Y0)、(X1、Y1)、(X1、Y2)。
2、次Bezier曲线的计算公式为:P(t)=(-P0+3P1-3P2+P3)t3+(3P0-6P1+3P2)t2+(-3P0+3P1)t+P0X(t)= (-X0+3X1-3X2+X3)t3+(3X0-6X1+3X2)t2+(-3X0+3X1)t+X0Y(t)= (-Y0+3Y1-3Y2+Y3)t3+(3Y0-6Y1+3Y2)t2+(-3Y0+3Y1)t+Y0其中P0、P1、P2、P3为四个已知的点,坐标分别为(X0、Y0)、(X1、Y1)、(X1、Y2) 、(X3、Y3)。
3、三次B样条函数绘制曲线的计算公式为:P(t)=[(-P0+3P1-3P2+3P3)t3+(3P0-6P1+3P2)t2+(-3P0+3P2)t+(P0+4P1+P2)]/6X(t)=[(-X0+3X1-3X2+3X3)t3+(3X0-6X1+3X2)t2+(-3X0+3X2)t+(X0+4X1+X2)]/6Y(t)=[(-Y0+3Y1-3Y2+3Y3)t3+(3Y0-6Y1+3Y2)t2+(-3Y0+3Y2)t+(Y0+4Y1+Y2)]/6其中P0、P1、P2、P3为四个已知的点,坐标分别为(X0、Y0)、(X1、Y1)、(X1、Y2) 、(X3、Y3)。
计算机图形学实验报告-实验3Bezier曲线
计算机图形学实验报告班级计算机工硕班学号 2011220456姓名王泽晶实验三:Bezier 曲线实验目的:通过本次试验,学生可以掌握Bezier 曲线的求值、升阶算法及Bezier 曲线绘制方法。
实验内容:1. 绘制控制多边形(使用鼠标左键指定多边形顶点,右键结束),使用白色折线段表示。
2. 绘制Bezier 曲线,使用红色,线宽为2,在右键结束控制多边形顶点指定时即执行。
Bezier 曲线是一种广泛应用于外形设计的参数曲线,它通过对一些特定点的控制来控制曲线的形状,我们称这些点为控制顶点。
现在我们来给出Bezier 曲线的数学表达式。
在空间给定1n +个点012,,,,n P P P P ,称下列参数曲线为n 次Bezier 曲线:,0()(),01ni i n i P t P B tt ==≤≤∑ 其中,()i n B t 是Bernstein 基函数,其表达式为:,!()(1)!()!i n ii n n B t t t i n i -=--,接着我们讨论3次Bezier 曲线,我们也采用将表达式改写为矩阵形式的方法,我们得到:3303!()(1)!(3)!i i ii P t P t t i i -==--∑32230123(1)3(1)3(1)t P t t P t t P t P =-+-+-+01323232323331,363,33,P P t t t t t t t t t P P ⎡⎤⎢⎥⎢⎥⎡⎤=-+-+-+-+⎣⎦⎢⎥⎢⎥⎣⎦01322313313630,,,133001000P P t t t P P --⎡⎤⎡⎤⎢⎥⎢⎥-⎢⎥⎢⎥⎡⎤=⎣⎦⎢⎥⎢⎥-⎢⎥⎢⎥⎣⎦⎣⎦试验步骤:添加成员函数,编写成员数代码为public class Al_deCasteljau {public function Al_deCasteljau(){}// de Casteljau递推算法的实现public function recursion( ctrlPts:Array, k:int , i:int ,t:Number ):Point {if ( k==0 ) return ctrlPts[i];return addPoints(multiplyNumToPoint((1 - t),recursion(ctrlPts, k-1, i, t)), multiplyNumToPoint(t , recursion(ctrlPts, k-1, i+1, t)));}public function multiplyNumToPoint(n:Number,p:Point):Point{return new Point(p.x * n,p.y * n);}public function addPoints(p1:Point,p2:Point):Point{return new Point(p1.x + p2.x,p1.y + p2.y);}public function minusPoints(p1:Point,p2:Point):Point{return new Point(p1.x - p2.x,p1.y - p2.y);}public function algorithm_deCasteljau(t:Number, ctrlPts:Array ):Point{var size:int = ctrlPts.length;return recursion( ctrlPts, size-1, 0, t );}public function upgradePoints(ctrlPts:Array):Array{var size:int = ctrlPts.length;var newPts:Array = new Array();newPts[0] = ctrlPts[0]; // i = 0for ( var i:int =1; i<size; ++i ){var factor:Number = i / size;newPts[i] = addPoints(multiplyNumToPoint( factor , ctrlPts[i-1] ) , multiplyNumToPoint((1 - factor) , ctrlPts[i]));}newPts[size] = ctrlPts[ctrlPts.length-1]; // i = n+1return newPts;}public function downgradePoints(ctrlPts:Array):Array{var size:int = ctrlPts.length;var newPts:Array = new Array();newPts[0] = ctrlPts[0]; // i = 0for ( var i:int=1; i<size-1; ++i ){var factor:Number = 1.0 /(size-1 - i);newPts[i] = multiplyNumToPoint(factor,minusPoints(multiplyNumToPoint(size-1 , ctrlPts[i]), multiplyNumToPoint(i , newPts[i-1])));}return newPts;}}编译运行得到如下结果:。
Bezier曲线B样条曲线
是一种特殊情况
Y
0 X
5.1 曲线的参数表 示
• 向量P与时间t有关: P=P(t),就是说P是时 间t的函数。用坐标表示为 :
• 若把参数t 换成一个普通意义的参数u, 则曲线的参数形式为:
• 例如:
是一条空
• 间曲线的参数形式。
• 注: 这是一条以点(0,1,3)为起点,
(3,2,5)为终点的线段
5.2 Bezier、B样条曲线的生成
• 3)三次Bezier曲线 • 当n=3时为三次Bezier曲线,此时P(t)为三
次多项式,有四个控制点,由于三次Bezier 曲线是用3根折线定义的3阶曲线,则有:
用矩阵表示为:
5.2 Bezier、B样条曲线的生成
5.2 Bezier、B样条曲线的生成
且第一点和最后一点在曲线上,第一条和最
后一条折线分别表示出曲线在起点和终点处
的切线方向。 Bezier曲线通常由特征多边形
的n+1个顶点定义一个n次多项式,即给定空
间n+1个点的位置矢量Pi(i=0,1,2,…,
n),则Bezier参数曲线上各点坐标的参数方
程其式中参(插数t的值取值公范式围为)[是 0,1]: ,i是有序集0~n中的一个整数值,表示 顶点顺序号。
但从计算机图形学和计算几何的角度来看, 还
是使用参数表示较好, 因为采用参数方法表示
曲线和曲面, 可以将其形状从特定坐标系的依
附性中解脱出来, 很容易借助计算机得以实现。
• 一个动点的u轨1 迹可以用位置向量P来描述,
如• 注下:图这所里示讨: 论的动点轨u2 迹是
Z
u
在三维空间中所表示的 曲线, 平面轨迹曲线只
是一个Bezier曲线特征多边形顶点的
计算机图形学实验报告B样条曲线
姓名:黄仁化学号:051017实验内容:B样条曲线实验目的:了解B样条曲线成条特点B样条曲线的方程定义为:P(t)=∑P i N i.k(t)i=0其中,P i(i=0,1,…,n)是控制多边形的顶点,N i.k(t)(i=0,1,…,n)称为k 阶(k-1次)B样条基函数,其中每一个称为B样条,它是一个由称为节点矢量的非递减的参数t的序列T:t0≤t1≤…≤t n+k所决定的k阶分段多项多,也即为k阶(k-1次)多项式样条。
B样条曲线算法描述:1.三次B是由Beizier曲线改进得到,由连续的四个离散点拟合一小段,它过四个点中最外的两端点,但不一定过当中的两点,各个小段合在一块组成一光滑曲线。
2.三次B样条曲线的基函数为G03(t)=1/6(-t^3+3*t^2-3*t+1)G13(t)=1/6(3*t^3-6*t^2+4)G23(t)=1/6(-3*t^3+3*t^2+3*t+1)G33(t)=1/6*t^33.三次B样条曲线段P3(t)=1/6*[t^3t^2t1][-1 3 -3 13 -6 3 0-3 03 0(T)1 41 0][p0 p1 p2 p3]-->(转置)四个离散点为p0 p1 p2 p34.B样条算法#include<graphics.h>#include<conio.h>#define N 10float px[N]={20,75,122,187,225,242,280,318,349,402}; float py[N]={98,265,154,152,243,298,102,202,248,130}; main(){float a0,a1,a2,a3,b0,b1,b2,b3;int k,x,y;float i,t,dt;int graphDriver=DETECT;int graphMode=0;initgraph(&graphDriver,&graphMode,""); setbkcolor(WHITE);setcolor(RED);line(50,300,600,300);line(100,10,100,320);dt=1/(float)N;for(k=0;k<N;k++){if(k==0)moveto(px[k]+100,300-py[k]);lineto(px[k]+100,300-py[k]);}setlinestyle(0,0,3);for(k=0;k<N-3;k++){a0=(px[k]+4*px[k+1]+px[k+2])/6;a1=(px[k+2]-px[k])/2;a2=(px[k]-2*px[k+1]+px[k+2])/2;a3=-(px[k]-3*px[k+1]+3*px[k+2]-px[k+3])/6;b0=(py[k]+4*py[k+1]+py[k+2])/6;b1=(py[k+2]-py[k])/2;b2=(py[k]-2*py[k+1]+py[k+2])/2;b3=-(py[k]-3*py[k+1]+3*py[k+2]-py[k+3])/6;for(i=0;i<N;i+=0.1){t=i*dt;x=100+a0+a1*t+a2*t*t+a3*t*t*t;y=300-(b0+b1*t+b2*t*t+b3*t*t*t);if(i==0.0)moveto(x,y);lineto(x,y);}}getch();closegraph();}运行结果。
计算机图形学--编程生成“三次贝塞尔”曲线
集美大学计算机工程学院实验报告课程名称计算机图形学教程实验名称实验五、编程生成“三次贝塞尔”曲线实验类型设计型姓名学号日期12月12日地点成绩教师一、实验目的:一方面,让学生对自由曲线的生成算法有更深入的理解,特别是对于曲线的逼近,能够通过实验编程来验证书上所提供的算法思想:另一方面,在图形程序设计方法(如设计各种各样的图形)、绘图函数的使用以及C和C++语言编程环境、程序的调试和测试方面受到比较系统和严格的训练。
二、实验内容:运用所学的三次贝塞尔曲线生成的算法,根据以下数据点[x, y]:[50, 100] [80, 230] [100, 270] [140, 160] [180, 50] [240, 65] [270, 120] [330, 230] [380, 230] [430, 150]计算出结果,并实现三段贝塞尔在屏幕上显示的功能三、实验要求:(1)3段三次贝塞尔曲线在衔接点上要连续,曲线整体效果要光滑。
(2)整个图形轮廓要清晰,色彩要分明四、实验环境:1.PC,CPU:P4 2.0GHz以上,内存:512M,硬盘:40GB以上;2.操作系统:Microsoft Windows 2000 /2003/XP;3.软件:VC或JAVA等。
五、实验内容及完成情况:#include "graphics.h"#include "conio.h"#include "stdio.h"typedef struct{double x,y;} DPOINT; //定义结构体class Bezier //定义Bezier类{private:DPOINT* bP;int m_maxIndex;void drawFrame();void drawCurve();void drawCurve(int p0,int p1,int p2,int p3);public:Bezier(DPOINT* p,int len); //定义构造函数void draw();};Bezier::Bezier(DPOINT* p,int len) //构造函数的实现{this ->bP=p;m_maxIndex=len-1;}void Bezier::draw() //通过公有函数调用私有函数{drawFrame();drawCurve();}void Bezier::drawFrame() //其功能是绘制出多边形和各个端点{setcolor(12);for(int i=0;i<m_maxIndex;i++){line( bP[i].x, bP[i].y, bP[i+1].x, bP[i+1].y ); //绘制多边形circle(bP[i].x, bP[i].y,5); //绘制各个端点}circle(bP[m_maxIndex].x,bP[m_maxIndex].y,5);}void Bezier::drawCurve() //实现多段Bezier曲线绘制的功能{for(int i=0;i<=m_maxIndex-3;i+=3){drawCurve(i,i+1,i+2,i+3);}}void Bezier::drawCurve(int p0,int p1,int p2,int p3) //实现绘制某一段Bezier曲线的功能{double tmpx=0.0;double tmpy=0.0;double t=0.0;for(;t<=1.0;t+=0.001){tmpx=(-bP[p0].x+3*bP[p1].x-3*bP[p2].x+bP[p3].x)*t*t* t+(3*bP[p0].x-6*bP[p1].x+3*bP[p2].x)*t*t+(-3*bP[p0].x+ 3*bP[p1].x)*t+bP[p0].x;tmpy=(-bP[p0].y+3*bP[p1].y-3*bP[p2].y+bP[p3].y)*t*t* t+(3*bP[p0].y-6*bP[p1].y+3*bP[p2].y)*t*t+(-3*bP[p0].y+ 3*bP[p1].y)*t+bP[p0].y;putpixel(tmpx,tmpy,3);}}void main() //主函数的实现{int graphdriver=DETECT,graphmode;initgraph(&graphdriver,&graphmode,"E:\\tc3\\bgi");setbkcolor(0);outtextxy(10,20,"n\n\n\n\n\n\ jisuan1013 2010810070 chengaowei");DPOINT* p;p=new DPOINT[10];p[0].x=50.0;p[0].y=100.0;p[1].x=80.0;p[1].y=230.0;p[2].x=100.0;p[2].y=270.0;p[3].x=140.0;p[3].y=160.0;p[4].x=180.0;p[4].y=50.0;p[5].x=240.0;p[5].y=65.0;p[6].x=270.0;p[6].y=120.0;p[7].x=330.0;p[7].y=230.0;p[8].x=380.0;p[8].y=230.0;p[9].x=430.0;p[9].y=150.0;Bezier bzr(p,10);bzr.draw();delete p;getch();closegraph();}运行结果:六、实验总结:通过这次实验,让我对自由曲线的生成算法有更深入的理解,特别是对于曲线的逼近,能够通过实验编程来验证书上所提供的算法思想,在图形程序设计方法(如设计各种各样的图形)、绘图函数的使用以及C和C++语言编程环境、程序的调试和测试方面受到比较系统和严格的训练。
计算机图形学实验4-----Hermite-Bezier-B样条三种曲线的绘制
实验四 Hermite Bezier B样条三种曲线的绘制一、实验目的了解和学习Hermite、Bezier、B样条三种曲线算法掌握基于 Win32、Visual C++环境MFC绘制图形配置过程制过程编程实现Hermite、Bezier、B样条三种曲线的绘制二、实验原理三次参数曲线1.曲线段可以用端点、切向量和曲线段之间的连续性等约束条件来定义2.两个端点和两端点处的切向量定义Hermite曲线;3.两个端点和另外两个控制端点切向量的点定义的Bezier曲线;4.由四个控制顶点定义的样条曲线。
三、实验关键代码void CDrawYTQXView::Hermite() //绘制Hermite三次插值样条{int a[4][4] ={{2,-2,1,1},{-3,3,-2,-1},{0,0,1,0},{1,0,0,0}};//Mh 矩阵系数int b[4][2];//边界点for(int i=0;i<4;i++){b[0][0]=p1[i][0];b[0][1]=p1[i][1];//起点的坐标b[1][0]=p1[i+1][0];b[1][1]=p1[i+1][1];//终点的坐标b[2][0]=p2[i][0];b[2][1]=p2[i][1];//起点的导数b[3][0]=p2[i+1][0];b[3][1]=p2[i+1][1];//终点的导数Caculate(a,b);CClientDC dc(this);CPen MyPen,*pOldPen;MyPen.CreatePen(PS_SOLID,1,RGB(0,0,255));pOldPen=dc.SelectObject(&MyPen);dc.MoveTo(p1[i][0],p1[i][1]);for(double t=0.0;t<=1;t+=1.0/400){int x=ROUND(pow(t,3)*result[0][0]+pow(t,2)*result[1][0]+ t*result[2][0]+result[3][0]);int y=ROUND(pow(t,3)*result[0][1]+pow(t,2)*result[1][1]+ t*result[2][1]+result[3][1]);dc.LineTo(x,y);}dc.SelectObject(pOldPen);MyPen.DeleteObject();}}void CDrawYTQXView::Caculate(int a[4][4],int b[4][2])//矩阵相乘{int i,j,k;for(i=0;i<4;i++)for(j=0;j<2;j++)result[i][j]=0; //矩阵清零for(i=0;i<2;i++)for(j=0;j<4;j++)for(k=0;k<4;k++)result[j][i]+=a[j][k]*b[k][i];}void CDrawYTQXView::DrawBezier()//绘制Bezier曲线{CClientDC dc(this);double x,y;int rate=400,n;n=CtrlPoint-1;for(double t=0;t<=1;t+=1.0/rate){x=0;y=0;for(int i=0;i<=n;i++){x+=pt[i].x*Cnk(n,i)*pow(t,i)*pow(1-t,n-i);y+=pt[i].y*Cnk(n,i)*pow(t,i)*pow(1-t,n-i);}dc.SetPixel(ROUND(x),ROUND(y),RGB(0,0,255)); //曲线颜色}}double CDrawYTQXView::Cnk(const int &n, const int &i)//Bernstein 第一项{return double(Factorial(n)/(Factorial(i)*Factorial(n-i)));}int CDrawYTQXView::Factorial(int m)//阶乘函数{int f=1;for(int i=1;i<=m;i++)f*=i;return f;}void CDrawYTQXView::DrawB3_curves() //绘制B样条曲线{CClientDC dc(this);int i,rate=10,m;long lx,ly;m=CtrlPoint-(3+1);double F03,F13,F23,F33;lx=ROUND((pt[0].x+4.0*pt[1].x+pt[2].x)/6.0); //t=0的起点x坐标ly=ROUND((pt[0].y+4.0*pt[1].y+pt[2].y)/6.0);//t=0的起点y坐标dc.MoveTo(lx,ly);CPen MyPen2,*pOldPen2;MyPen2.CreatePen(PS_SOLID,2,RGB(0,0,255)); //颜色设置pOldPen2=dc.SelectObject(&MyPen2);for(i=1;i<m+2;i++) //m+1段三次样条曲线{for(double t=0;t<=1;t+=1.0/rate){F03=(-t*t*t+3*t*t-3*t+1)/6;//计算F0,3(t)F13=(3*t*t*t-6*t*t+4)/6;//计算F1,3(t)F23=(-3*t*t*t+3*t*t+3*t+1)/6;//计算F2,3(t)F33=t*t*t/6;//计算B3,3(t)lx=ROUND(pt[i-1].x*F03+pt[i].x*F13+pt[i+1].x*F23+pt[i+2].x*F33 );ly=ROUND(pt[i-1].y*F03+pt[i].y*F13+pt[i+1].y*F23+pt[i+2].y*F33 );dc.LineTo(lx,ly);}}dc.SelectObject(pOldPen2);MyPen2.DeleteObject();}void CDrawYTQXView::DrawCharPolygon()//绘制控制多边形{CClientDC dc(this);CPen MyPen,*pOldPen;MyPen.CreatePen(PS_SOLID,2,RGB(0,0,0)); //控制多边形pOldPen=dc.SelectObject(&MyPen);for(int i=0;i<CtrlPoint;i++){if(i==0){dc.MoveTo(pt[i]);dc.Ellipse(pt[i].x-2,pt[i].y-2,pt[i].x+2,pt[i].y+2);}else{dc.LineTo(pt[i]);dc.Ellipse(pt[i].x-2,pt[i].y-2,pt[i].x+2,pt[i].y+2);}}dc.SelectObject(pOldPen);MyPen.DeleteObject();}void CDrawYTQXView::OnLButtonDown(UINT nFlags, CPoint point)//获得屏幕控制点坐标{// TODO: Add your message handler code here and/or call default CView::OnLButtonDown(nFlags, point);if(Flag){pt[CtrlPoint].x=point.x;pt[CtrlPoint].y=point.y;if(CtrlPoint<N_MAX_POINT)CtrlPoint++;elseFlag=false;DrawCharPolygon();}else DrawCharPolygon1();}void CDrawYTQXView::OnRButtonDown(UINT nFlags, CPoint point)//调用绘制函数{// TODO: Add your message handler code here and/or call default Flag=false;if(Sign==0)Hermite();if(Sign==1)DrawBezier();if(Sign==2)DrawB3_curves();CView::OnRButtonDown(nFlags, point);}四、实验结果1、绘制Hermite曲线2、绘制Bezier曲线3. 绘制B样条曲线五、心得体会通过实验进一步学习和了解MFC的菜单的实现及其响应函数的实现,并设置鼠标的左键激活绘制多边形,右键激活绘制Hermite、Bezier、B样条三种曲线。
图形学Bezier曲线绘制
五、实验代码及原理://计算v的m次方double CExp11View::Power(double v, int m){ int i=1;double temp=1.0;if(m==0||v==0) return (1.0);elsefor(i=1;i<=m;i++) temp=temp*v; //n个v相乘,v^m return temp;}//计算n的阶乘double CExp11View::NFactor(int n){ double factor=1;if(n==0) return (factor);while(n>0){ factor=n*factor;n=n-1;}return(factor);}//Bezier函数const N=3; //控制点数N+1const D=20; //分段数int CExp11View::Bezier(CDC* pDC,double P[21][2]){const width=600;const height=300;double B[N+1]; //基函数double Qx[D+1],Qy[D+1]; //各分段坐标点double AA,BB,CC,t;int i,j,e,cx,cy;cx=(int)P[0][0]; cy=(int)P[0][1]; //画特征多边形pDC->MoveTo(cx+width,height-cy);for(i=1;i<=N;i++){ cx=(int)P[i][0]; cy=(int)P[i][1];pDC->LineTo(cx+width,height-cy);}Qx[0]=P[0][0]; Qy[0]=P[0][1];Qx[D]=P[N][0]; Qy[D]=P[N][1];for(e=1;e<D;e++) //对于给定t,计算Bi,n(t){ t=(double)e/D;{ AA=NFactor(N);BB=NFactor(j);CC=NFactor(N-j);B[j]=AA/(BB*CC)*Power(t,j)*Power((1-t),(N-j));}Qx[e]=0; Qy[e]=0; //对于给定的t,计算各分段坐标点for(j=0;j<=N;j++){ Qx[e]=Qx[e]+B[j]*P[j][0];Qy[e]=Qy[e]+B[j]*P[j][1];}}cx=(int)(Qx[0]+0.5); cy=(int)(Qy[0]+0.5); //画出各分段坐标点连接pDC->MoveTo(cx+width,height-cy);for(e=1;e<=D;e++){ cx=(int)(Qx[e]+0.5); cy=(int)(Qy[e]+0.5);pDC->LineTo(cx+width,height-cy);}return 0;}//Bline函数const n=3; //特征多边形边数const k=3; //曲线阶数(曲线次数为C-1次)const width=100;const height=600;void CExp11View::Bline(CDC *pDC,double P[n+1][2],int ZD){double **Q= new double*[ZD+1];for(int a=0;a<ZD+1;a++) Q[a]=new double[2];//插值点坐标int u[n+k+1]; //纽结向量double N[n+k+1][k+1]; //基函数N(i,k)double D,E,t;int i,j,F,H,w,cx,cy;cx=(int)P[0][0]; cy=(int)P[0][1]; //画特征多边形pDC->MoveTo(cx+width,height-cy);for(i=1;i<=n;i++){ cx=(int)P[i][0]; cy=(int)P[i][1];pDC->LineTo(cx+width,height-cy);}for(i=0;i<=n+k;i++) //计算纽结向量{ if(i<k) u[i]=0;if(k<=i && i<=n) u[i]=i-k+1;if(i>n) u[i]=n-k+2;}{ for(i=0;i<=n+k-1;i++) //计算1阶基N[i][1]{ if(i==w) N[i][1]=1.0; //N(i,1)(t)=1,if u(w)<=t<u(w+1) and u(w)<u(w+1)else N[i][1]=0.0;}for(F=0;F<=ZD;F++){ t=(double)F/ZD+u[w];for(j=2;j<=k;j++) //计算不同值下的j阶基N[i][j]for(i=0;i<=n+k-j;i++){ if(N[i][j-1]==0)D=0;elseD=((t-u[i])*N[i][j-1])/(u[i+j-1]-u[i]);if(N[i+1][j-1]==0 )E=0;elseE=((u[i+j]-t)*N[i+1][j-1])/(u[i+j]-u[i+1]);N[i][j]=D+E;}j=k;for(H=0;H<=1;H++) //计算P[i]*N[i][j]{ Q[F][H]=0.0;for(i=0;i<=n;i++)Q[F][H]= Q[F][H]+P[i][H]*N[i][j];}}for(F=0;F<=ZD;F++) //画插值点连接{ if(F==0 && w==k-1){ cx=(int)(Q[0][0]+0.5); cy=(int)(Q[0][1]+0.5);pDC->MoveTo(cx+width,height-cy);}else{ cx=(int)(Q[F][0]+0.5); cy=(int)(Q[F][1]+0.5);pDC->LineTo(cx+width,height-cy);}}}}//第一条贝塞尔曲线void CExp11View::OnMenuitem32773(){CDC *pDC=GetDC(); //先获取给定窗口用户区的显示器描述表double P[D+1][2]={{180-500,0},{40-500,210+50},{360-500,210-20},{-500,0}}; //控制点坐标Bezier(pDC,P);}//第二条贝塞尔曲线void CExp11View::OnMenuitem32774(){CDC *pDC=GetDC(); //先获取给定窗口用户区的显示器描述表double P[D+1][2]={{0-50,0},{40-50,210},{360-50,210},{180-50,0}}; //控制点坐标Bezier(pDC,P);}//第三条贝塞尔曲线void CExp11View::OnMenuitem32775(){CDC *pDC=GetDC(); //先获取给定窗口用户区的显示器描述表double P[D+1][2]={{0+400,0},{40+400,210-80},{180+400,0},{360+400,210+20}}; //控制点坐标Bezier(pDC,P);}//第一条B样条曲线void CExp11View::OnMenuitem32776(){// TODO: Add your command handler code hereCDC *pDC=GetDC();//先获取给定窗口用户区的显示器描述表doubleP[n+1][2]={{100-200,100-100},{200-200,300-100},{400-200,300-100},{300-200,100-100}};Bline(pDC,P,3);}//第二条B样条曲线void CExp11View::OnMenuitem32777(){// TODO: Add your command handler code hereCDC *pDC=GetDC();//先获取给定窗口用户区的显示器描述表doubleP[n+1][2]={{100+300,100-100},{200+300,300-100},{400+300,300-100},{300+300,100-100}};Bline(pDC,P,5);}//第三条B样条曲线void CExp11View::OnMenuitem32778(){// TODO: Add your command handler code hereCDC *pDC=GetDC();//先获取给定窗口用户区的显示器描述表doubleP[n+1][2]={{100+800,100-100},{200+800,300-100},{400+800,300-100},{300+800,100-100}};Bline(pDC,P,20);}六、实验结果:。
南昌大学信工学院计算机图形学实验报告(附详细代码)
实验报告实验课程:计算机图形学学生姓名:XXX学号:XXX专业班级:计算机科学与技术X班20XX年XX月XX日目录实验一直线和圆的生成 (3)实验二区域填充 (12)实验三裁剪算法 (15)实验四Bezier曲线的绘制 (23)实验五B样条曲线的绘制 (27)南昌大学实验报告学生姓名:学号:专业班级:实验类型:□验证□综合□设计□创新实验日期:实验成绩:实验一直线和圆的生成一、实验项目名称直线和圆的生成二、实验目的1、掌握DDA、Bresenham 直线生成算法;2、掌握中点画圆生成算法三、实验要求1、编程实现DDA、Bresenham算法生成直线2、编程实现中点画圆的算法四、实验步骤1、根据实验要求分析实验,并写出相应算法的实现2、选择适当语言实现算法;3、调试程序。
五、实验内容1、Bresenham画线算法的实现#include<gl\glut.h>#include<stdlib.h>#include<math.h>void init(void){glClearColor(1.0,1.0,1.0,0.0);glMatrixMode(GL_PROJECTION);gluOrtho2D(0.0,600.0,0.0,500.0);}void setPixel(int x,int y){glBegin(GL_POINTS);glVertex2i(x,y);glEnd();}void lineBres(int x0,int y0,int xEnd,int yEnd) {int dx=abs(xEnd-x0),dy=abs(yEnd-y0);int p=2*dy-dx;int twoDy=2*dy,twoDyMinusDx=2*(dy-dx);int x,y;if(x0>xEnd){x=xEnd;y=yEnd;}else{x=x0;y=y0;}setPixel( x, y);while(x<xEnd){x++;if(p<0)p+=twoDy;else{y++;p+=twoDyMinusDx;}setPixel( x, y);}}void lineSegment(void){glClear(GL_COLOR_BUFFER_BIT);glColor3f(0.0,0.0,1.0);lineBres(50,50,400,300);glFlush();}void main(int argc,char** argv){glutInit(&argc,argv);glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);glutInitWindowPosition(50,100);glutInitWindowSize(400,300);glutCreateWindow("An Line OpenGL Program");init();glutDisplayFunc(lineSegment);glutMainLoop();}2、DDA算法的实现#include<gl\glut.h>#include<math.h>void init(void){glClearColor(1.0,1.0,1.0,0.0);glMatrixMode(GL_PROJECTION);gluOrtho2D(0.0,600.0,0.0,500.0);}void setPixel(int x,int y){glBegin(GL_POINTS);glVertex2i(x,y);glEnd();}inline int round(const float a){return int(a+0.5);}void lineDDA (int x0,int y0,int xEnd,int yEnd){int dx=xEnd-x0,dy=yEnd-y0,steps,k;float xIncrement,yIncrement,x=x0,y=y0;if(abs(dx)>abs(dy))steps=abs(dx);elsesteps=abs(dy);xIncrement=GLfloat(dx)/GLfloat(steps);yIncrement=GLfloat(dy)/GLfloat(steps);setPixel( x, y);for(k=0;k<steps;k++){x+=xIncrement;y+=yIncrement;setPixel( x, y);}}void lineSegment(void){glClear(GL_COLOR_BUFFER_BIT);glColor3f(1.0,0.0,0.0);lineDDA(50,50,400,300);glFlush();}void main(int argc,char** argv){glutInit(&argc,argv);glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);glutInitWindowPosition(50,100);glutInitWindowSize(400,300);glutCreateWindow("DDA OpenGL Program");init();glutDisplayFunc(lineSegment);glutMainLoop();}3、圆的生成#include<gl\glut.h>#include <math.h>const int n = 20;const GLfloat R = 0.5f;const GLfloat Pi = 3.1415926536f;void init(void){glClearColor(1.0,1.0,1.0,0.0);glMatrixMode(GL_PROJECTION);gluOrtho2D(0.0,200.0,0.0,150.0);}void myDisplay(void){int i;glClear(GL_COLOR_BUFFER_BIT);glColor3f(1.0,0.0,0.0);glBegin(GL_POL YGON);for(i=0; i<n; ++i)glVertex2f(R*cos(2*Pi/n*i), R*sin(2*Pi/n*i));glEnd();glFlush();}void main(int argc,char** argv){glutInit(&argc,argv);glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);glutInitWindowPosition(50,100);glutInitWindowSize(500,500);glutCreateWindow("An Circle OpenGL Program");init();glutDisplayFunc(myDisplay);glutMainLoop();return ;}4、修改后的圆的生成#include <GL/glut.h>#include <math.h>const int n = 20;const GLfloat R = 0.5f;const GLfloat Pi = 3.1415926536f;void myDisplay(void){int i;glClear(GL_COLOR_BUFFER_BIT);glColor3f(1.0,0.0,0.0);glBegin(GL_POL YGON);for(i=0; i<n; ++i)glVertex2f(R*cos(2*Pi/n*i), R*sin(2*Pi/n*i));glEnd();glFlush();}int main(int argc, char *argv[]){glutInit(&argc, argv);glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);glutInitWindowPosition(100, 100);glutInitWindowSize(400, 400);glutCreateWindow("画圆的程序");glutDisplayFunc(&myDisplay);glutMainLoop();return 0}5、中点画圆算法#include<gl/glut.h>#include<stdlib.h>#include<math.h>void init(void){glClearColor(1.0,1.0,1.0,0.0);glMatrixMode(GL_PROJECTION);gluOrtho2D(0.0,200.0,0.0,150.0);}class screenPt{private:GLint x,y;public:screenPt(){x=y=0;}void setCoords(GLint xCoordValue,GLint yCoordValue){ x=xCoordValue;y= yCoordValue;}GLint getx() const{return x;}GLint gety() const{return y;}void incrementx(){x++;}void decrementy(){y--;}void setPixel(GLint xCoord,GLint yCoord){glBegin(GL_POINTS);glVertex2i(xCoord,yCoord);glEnd();}void circleMidpoint(GLint xc,GLint yc,GLint radius) {screenPt circPt;GLint p=1-radius;circPt.setCoords(0,radius);void cieclePlotPoints(GLint,GLint,screenPt);cieclePlotPoints(xc,yc,circPt);while(circPt.getx()<circPt.gety()){circPt.incrementx();if (p < 0)p += 2 * circPt.getx() + 1;else {circPt.decrementy();p += 2 * (circPt.getx() - circPt.gety()) + 1;}cieclePlotPoints(xc,yc,circPt);}}void cieclePlotPoints(GLint xc,GLint yc,screenPt circPt) {setPixel(xc+circPt.getx(),yc+circPt.gety());setPixel(xc-circPt.getx(),yc+circPt.gety());setPixel(xc+circPt.getx(),yc-circPt.gety());setPixel(xc-circPt.getx(),yc-circPt.gety());setPixel(xc+circPt.gety(),yc+circPt.getx());setPixel(xc-circPt.gety(),yc+circPt.getx());setPixel(xc+circPt.gety(),yc-circPt.getx());setPixel(xc-circPt.gety(),yc-circPt.getx());}void myDisplay(void){glClear(GL_COLOR_BUFFER_BIT);glColor3f(0.0,1.0,0.0);circleMidpoint(50,50,20);glFlush();void main(int argc,char** argv){glutInit(&argc,argv);glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);glutInitWindowPosition(50,100);glutInitWindowSize(400,300);glutCreateWindow("A Circle OpenGL Program");init();glutDisplayFunc(myDisplay);glutMainLoop();}六、实验结果Bresenham画线算法的实现:DDA算法的实现:圆的生成:中点画圆算法:七、实验心得课本上有画直线和中点画圆的核心代码,只要加上main函数和窗口定义等的基本函数,稍微修改就可以得到完整的程序,比较简单。
第10章-曲面与曲线-Hermite和Bezier曲线
三次Hermite曲线 曲线(3/7) 三次 曲线
– 合并
1 0 ⇒GH • MH • 0 0 1 0 0 1 1 1 = [P P R0 0 1 1 0 2 1 0 3
−1
R ] = GH 1
取 为
– 解(不唯一) 不唯一)
1 0 MH = 0 0 1 0 0 1 0 1 1 1 = 0 1 0 2 1 0 3 0 0 −3 2 0 3 − 2 1 −2 1 0 −1 1
北大计算机系多媒体与人机交互
12
Bezier曲线(4/24) 曲线( 曲线 )
– 升阶公式
i +1 n +1 − i BEZi,n (t) = BEZi+1,n+1(t) + BEZi,n+1(t) n +i n +1
– 导数
BEZi,n (t) = n(BEZi−1,n−1(t) − tBEZi,n−1(t))
北大计算机系多媒体与人机交互
5
三次Hermite曲线 曲线(5/7) 三次 曲线
• 形状控制
– 改变端点位置矢量 P , P 0 1 – 调节切矢量 R0 , R1 的方向
北大计算机系多媒体与人机交互
6
三次Hermite曲线 曲线(6/7) 三次 曲线
– 调节切矢量 R0 , R1的长度
– 控制顶点
• Bezier曲线的性质 曲线的性质
– 端点位置
P(t) |t=0 = P 0 P(t) |t=1= P n
北大计算机系多媒体与人机交互
16
Bezier曲线(8/24) 曲线( 曲线 )
– 端点切矢量
计算机图形学Bezeir算法实验报告
实验四 自由曲线绘制算法1. 实验目的:1.掌握曲线的表示形式、曲线的连续性条件、拟合和逼近的基本概念2.掌握Bezier 曲线的性质3.编程实现Bezier 曲线生成算法2. 实验描述:绘制三次Bezier 曲线,可以采用公式法或德卡斯特里奥(De Casteliau )算法绘制。
3. 算法设计:在空间给定1n +个点012,,,,n PP P P ,称下列参数曲线为n 次Bezier 曲线:,0()(),01ni i n i P t P B tt ==≤≤∑其中,()i n B t 是Bernstein 基函数,其表达式为:,!()(1)!()!i n ii n n B t t ti n i -=--,接着我们讨论3次Bezier 曲线,我们也采用将表达式改写为矩阵形式的方法,我们得到:3303!()(1)!(3)!i i ii P t P t t i i -==--∑32230123(1)3(1)3(1)t P t t P t t P t P =-+-+-+01323232323331,363,33,P P t t t t t t t t t P P ⎡⎤⎢⎥⎢⎥⎡⎤=-+-+-+-+⎣⎦⎢⎥⎢⎥⎣⎦01322313313630,,,133001000P P t t t P P --⎡⎤⎡⎤⎢⎥⎢⎥-⎢⎥⎢⎥⎡⎤=⎣⎦⎢⎥⎢⎥-⎢⎥⎢⎥⎣⎦⎣⎦4. 源程序://1)TestView.hclass CTestView : public CView {…….protected:bool Flag;//标志CPoint *pt;//顶点int CtrlPoint;//控制多边形顶点……..}2) //TestView.cpp#include "math.h"//数学头文件#define N_MAX_POINT 10//控制多边形的最大顶点数#define ROUND(a) int(a+0.5) //四舍五入。
离散点拟合曲线,Bezier,B样条演示课件
1 1 0P2
(0 t 1)
二次Bezier曲线参数方程的矩阵形式:
1 2 P(t)[t2 t 1]2 2
1 0
1P0 0P1 0P2
二次B样条曲线参数方程的分量形式:
§3 B样条曲线
分量形式为:
x(t)a0 a1t a2t2 y(t)b0 b1t b2t2
(0t 1)
其中
a0
1 2
给出2个一般标准:
§1 概述
1. C 1连续 在连接点 pj 处,若两曲线段的切线斜率相等(相同 的切线),或者说一阶导数连续,即
pj() pj()
pj
称两曲线段在连接点 pj 处的光滑连接达到C 1连续。
2. C 2连续
在连接点 pj 处,不仅两曲线段的切线斜率相同,而 且切线斜率的变化率也相同,即
上述参数方程可写为:
P (t) A 0 A 1 t A 2 t2 0 t 1
②
方程②称为曲线的参数矢量方程。
在构建曲线方程时,通常采用方程②的矢量形式;在 绘制曲线时,通常采用方程①的分量形式。
P(t)x y((tt))b a0 0b a1 1tb a2 2t2
§1 概述
四、曲线段的光滑连接
当平面上已知数据点较多时,针对所有点拟合曲线方程 有时非常困难,或者得到的曲线方程非常复杂、不实用。
当步长极小时,所绘出的直线连线在视觉上便是一条 光滑的曲线。
求相邻离散点之间若干数据点的问题称为插值问题。
§1 概述
2. “平均通过”式
当已知数据点有一定误差时,所 拟合的曲线不通过所有已知点,曲线 代表的是这些数据点的变化趋势。
要求:设计的曲线方程与
所有已知点的“距离”总和最
贝塞尔曲线和B样条曲线
§4.3 贝塞尔曲线和B 样条曲线在前面讨论的抛物样条和三次参数样条曲线,他们的共同特点是:生成的曲线通过所有给定的型值点。
我们称之为“点点通过”。
但在实际工作中,往往给出的型值点并不是十分精确,有的点仅仅是出于外观上的考虑。
在这样的前提下,用精确的插值方法去一点点地插值运算就很不合算;另外,局部修改某些型值点,希望涉及到曲线的范围越小越好,这也是评价一种拟合方法好坏的指标之一。
针对以上要求,法国人Bezier 提出了一种参数曲线表示方法,称之为贝塞尔曲线。
后来又经Gorgon, Riesenfeld 和Forrest 等人加以发展成为B 样条曲线。
一、贝塞尔曲线贝塞尔曲线是通过一组多边折线的各顶点来定义。
在各顶点中,曲线经过第一点和最后一点,其余各点则定义曲线的导数、阶次和形状。
第一条和最后一条则表示曲线起点和终点的切线方向。
1.数学表达式n+1个顶点定义一个n 次贝塞尔曲线,其表达式为:)()(0,t B p t p ni n i i ∑== 10≤≤t),...,2,1,0(n i p i =为各顶点的位置向量,)(,t B n i 为伯恩斯坦基函数i n i n i t t n i n t B ---=)1()!1(!!)(,2.二次贝塞尔曲线需要3个顶点,即210,,p p p ,将其代入曲线表达式:2,222,112,00)(B p B p B p t p ++=220202,021)1()1()!02(!0!2t t t t t B +-=-=--=-21212,122)1(2)1()!12(!1!2t t t t t t B -=-=--=-22222,2)1()!22(!2!2t t t B =--=-221202)22()21()(p t p t t p t t t p +-++-=[]⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡--=21020010221211p p p t t 10≤≤t 2102)21(2)1(2)(tp p t p t t p +-+-=')(222)0(0110p p p p p -=+-=' 0)0(p p =)(222)1(1221p p p p p -=+-=' 2)1(p p =当21=t 时: 21021041214141)412212()412121(21p p p p p p p ++=+⋅-⋅++⋅-=⎪⎭⎫⎝⎛)](21[21201p p p ++= 02210212)2121(2)121(221p p p p p p -=⋅+⋅-+-=⎪⎭⎫⎝⎛'3.三次贝塞尔曲线三次贝塞尔曲线需要4个点,即0p 、1p 、2p 、3p 。
计算机图形学Bezeir算法实验报告
实验四 自由曲线绘制算法1.实验目的:1.掌握曲线的表示形式、曲线的连续性条件、拟合和逼近的基本概念2.掌握Bezier 曲线的性质3.编程实现Bezier 曲线生成算法2.实验描述:绘制三次Bezier 曲线,可以采用公式法或德卡斯特里奥(De Casteliau )算法绘制。
3.算法设计:在空间给定1n +个点012,,,,n P PP P ,称下列参数曲线为n 次Bezier 曲线:,0()(),01n i i n i P t PB t t ==≤≤∑其中,()i n B t 是Bernstein 基函数,其表达式为:,!()(1)!()!i n ii n n B t t t i n i -=--,接着我们讨论3次Bezier 曲线,我们也采用将表达式改写为矩阵形式的方法,我们得到:3303!()(1)!(3)!i i ii P t P t t i i -==--∑32230123(1)3(1)3(1)t P t t P t t P t P =-+-+-+01323232323331,363,33,P P t t t t t t t t t P P ⎡⎤⎢⎥⎢⎥⎡⎤=-+-+-+-+⎣⎦⎢⎥⎢⎥⎣⎦01322313313630,,,133001000P P t t t P P --⎡⎤⎡⎤⎢⎥⎢⎥-⎢⎥⎢⎥⎡⎤=⎣⎦⎢⎥⎢⎥-⎢⎥⎢⎥⎣⎦⎣⎦4.源程序://1)TestView.hclass CTestView : public CView {…….protected:bool Flag;//标志CPoint *pt;//顶点int CtrlPoint;//控制多边形顶点……..}2) //TestView.cpp#include "math.h"//数学头文件#define N_MAX_POINT 10//控制多边形的最大顶点数#define ROUND(a) int(a+0.5) //四舍五入。
计算机图形学——绘制Bezier曲线
计算机图形学实验报告专业:信息与计算科学班级: 1002班学号: **********姓名: ****实验目的:(1)掌握直线的参数表示法。
(2)掌握德卡斯特里奥算法的几何意义。
(3)掌握绘制二维Bezier曲线的方法。
实验要求:(1)使用鼠标左键绘制个数为10以内的任意控制点,使用直线连接构成控制多边形。
(2)使用鼠标右键绘制Bezier曲线。
(3)在状态栏显示鼠标的位置坐标。
(4)B ezier曲线使用德卡斯特里奥算法绘制。
实验算法:Bezier曲线的分割递推德卡斯特里奥算法给定空间n+1个点P i(i=0,1,2,…,n)及参数t,有P r i(t)=(1-t)P1-r i(t)+t P1-r1i+(t)式中,r=1,2,…,n;i=0,1,…,n-r;t∈[0,1]。
且规定当r=0时,P0i(t)=P i, P n0(t)是在曲线上具有参数t的点。
德卡斯特里奥算法的基础就是在矢量−−→−PP10上选择一个点P,使得P点划分矢量−−→−PP10为|PP0|:|PP1|=t:1-t,给定点P0、P1的坐标以及t的值,点P的坐标为P=P0+t(P1-P0)=(1-t)P0+tP1。
式中,t∈[0,1]。
定义贝塞尔曲线的控制点编号为P r i,其中,r表示迭代次数。
德卡斯特里奥证明了,当r=n时,P n0表示Bezier曲线上的点。
函数功能介绍1.德卡斯特里奥函数:long CMy12View::DeCasteliau(double t,long *p){double P[N_MAX_POINT][N_MAX_POINT];int n=CtrlPNum-1;for(int k=0;k<=n;k++){P[0][k]=p[k];}for(int r=1;r<=n;r++){for(int i=0;i<=n-r;i++){P[r][i]=(1-t)*P[r-1][i]+t*P[r-1][i+1];}}return(long(P[n][0]));}函数功能介绍:此函数为德卡斯特里奥算法函数。
实验四Bezier曲线生成算法实现
计算机图形学》实验报告(实验四,.Bezier曲线生成算法实现、实验目的及要求三次Bezier曲线及de Casteljau算法以及b样条曲线、理论基础详见教材!三、算法设计与分析Bezier 曲线生成算法int degree=3,i,x,y;float t;float coeff_x[4]={50.0,200.0,200.0,500.0};float coeff_y[4]={50.0,300.0,50.0,200.0};pDC->MoveTo(coeff_x[0],coeff_y[0];for(i=1;i<=3;i++ pDC->LineTo(coeff_x[i],coeff_y[i];for(t=0;t<=1;t+=0.001 x=hornbez(degree,coeff_x,t;y=hornbez(degree,coeff_y,t;pDC->SetPixel(x,y,RGB(0,0,0;float CMy2View::hornbez(int degree,float coeff[],float t int i,n_choose_i;float fact,t1,aux;t1=1.0-t;fact=1.0;n_choose_i=1;aux=coeff[0]*t1;for(i=1;i fact =fact*t;n_choose_i=n_choose_i*(degree-i+1/i;aux=(aux+fact*n_choose_i*coeff[i]*t1;aux=aux+fact*t*coeff[degree];return aux;de Casteljau 算法void CTuView::bezpoint(int degree,int npoints,float *coeff,float points[] float t,delt;int i;delt=1.0/(floatnpoints;t=0.0;for (i=0;i points[i]=decas(degree,coeff,t;t=t+delt;float CTuView::decas(int degree,float *coeff,float t int r,i;float t1;float coeffa[10];t1=1.0-t;for (i=0;i<=degree;i++ coeffa[i]=coeff[i];for(r=1;r<=degree;r++ for (i=0;i<=degree-r;i++ coeffa[i]=t1*coeffa[i]+t*coeffa[i+1];return coeffa[0];主函数:void CTuView::OnDraw(CDC* pDCCTuDoc* pDoc = GetDocument(;ASSERT_VALID(pDoc;// TODO: add draw code for native data here int degree=5,npoints=1000,i;float coeffx[]={10,40,265,300,400,500};float coeffy[]={20,130,160,90,300,100};float points1[1000],points2[1000];for (i=0;i pDC->MoveTo((intcoeffx[i],(intcoeffy[i];pDC->LineTo ((intcoeffx[i+1],(intcoeffy[i+1];bezpoint(degree,npoints,coeffx,points1;bezpoint(degree,npoints,coeffy,points2;for(i=0;ipDC->SetPixel((intpoints1[i],(intpoints2[i],RGB(123,12 3,123;B样条曲线void CBView::bsp(int degree,int l,float*coeff,float *knot,int dense,float *points,int *point_num int i,ii;float u;*point_num=0;for(i=degree-1;i if(knot[i+1]>knot[i] for(ii=0;iiu=knot[i]+ii*(knot[i+1]-knot[i]/dense;points[*point_num]=deboor(degree,coeff,knot,u,i;*point_num=(*point_num+1;float CBView::deboor(int degree,float *coeff,float*knot,float u,int i int k,j;float t1,t2;float coeffa[30];for (j=i-degree+1;j<=i+1;j++ coeffa[j]=coeff[j];for (k=1;k<=degree;k++ for(j=i+1;j>=i-degree+k+1;j-- t1=(knot[j+degree-k]-u/(knot[j+degree-k]-knot[j-1];t2=1.0-t1;coeffa[j]=t1*coeffa[j-1]+t2*coeffa[j];return coeffa[i+1];}主函数:void CBView::OnDraw(CDC* pDCCBDoc* pDoc = GetDocument(;ASSERT_VALID(pDoc;// TODO: add draw code for native data here int k,n; int degree,i,a;int dense=290,l=5;float coeffx[]={10,40,265,300,400,500,600};float coeffy[]={20,130,160,90,300,100,300};float points1[2000],points2[2000];float knot[]={0,0,0,0,0,1,2,2,2,2,2};int *point_num;k=5,n=5;/*n+1 个点*/ degree=5;a=0;point_num=&a;for (i=0;i<6;i++ pDC->MoveTo((intcoeffx[i],(intcoeffy[i]; pDC->LineTo ((intcoeffx[i+1],(intcoeffy[i+1];}bsp( degree,l,coeffx,k no t,de nse,poin ts1, point_num;bsp( degree,l,coeffy,k no t,de nse,poin ts2 ,point_num;for(i=0;i<2000;i++ p DC->Set Pi xel((i ntpoin ts1[i],(i ntpoin ts2[i],RGB(123,123,123;四、程序调试及结果的分析1、de Casteljau图形曲线四、实验心得及建议由于最近考试,这次的实验报告提交的比较晚。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验四 Hermite Bezier B样条三种曲线的绘制
一、实验目的
➢了解和学习Hermite、Bezier、B样条三种曲线算法
➢掌握基于 Win32、Visual C++环境MFC绘制图形配置过程制过程
➢编程实现Hermite、Bezier、B样条三种曲线的绘制
二、实验原理
✧三次参数曲线
1.曲线段可以用端点、切向量和曲线段之间的连续性等约束条件来定义
2.两个端点和两端点处的切向量定义Hermite曲线;
3.两个端点和另外两个控制端点切向量的点定义的Bezier曲线;
4.由四个控制顶点定义的样条曲线。
三、实验关键代码
void CDrawYTQXView::Hermite() //绘制Hermite三次插值样条
{
int a[4][4] ={{2,-2,1,1},{-3,3,-2,-1},{0,0,1,0},{1,0,0,0}};//Mh 矩阵系数
int b[4][2];//边界点
for(int i=0;i<4;i++)
{
b[0][0]=p1[i][0];b[0][1]=p1[i][1];//起点的坐标
b[1][0]=p1[i+1][0];b[1][1]=p1[i+1][1];//终点的坐标
b[2][0]=p2[i][0];b[2][1]=p2[i][1];//起点的导数
b[3][0]=p2[i+1][0];b[3][1]=p2[i+1][1];//终点的导数
Caculate(a,b);
CClientDC dc(this);
CPen MyPen,*pOldPen;
MyPen.CreatePen(PS_SOLID,1,RGB(0,0,255));
pOldPen=dc.SelectObject(&MyPen);
dc.MoveTo(p1[i][0],p1[i][1]);
for(double t=0.0;t<=1;t+=1.0/400)
{
int x=ROUND(pow(t,3)*result[0][0]+pow(t,2)*result[1][0]
+ t*result[2][0]+result[3][0]);
int y=ROUND(pow(t,3)*result[0][1]+pow(t,2)*result[1][1]
+ t*result[2][1]+result[3][1]);
dc.LineTo(x,y);
}
dc.SelectObject(pOldPen);
MyPen.DeleteObject();
}
}
void CDrawYTQXView::Caculate(int a[4][4],int b[4][2])//矩阵相乘{
int i,j,k;
for(i=0;i<4;i++)
for(j=0;j<2;j++)
result[i][j]=0; //矩阵清零
for(i=0;i<2;i++)
for(j=0;j<4;j++)
for(k=0;k<4;k++)
result[j][i]+=a[j][k]*b[k][i];
}
void CDrawYTQXView::DrawBezier()//绘制Bezier曲线
{
CClientDC dc(this);
double x,y;
int rate=400,n;
n=CtrlPoint-1;
for(double t=0;t<=1;t+=1.0/rate)
{
x=0;y=0;
for(int i=0;i<=n;i++)
{
x+=pt[i].x*Cnk(n,i)*pow(t,i)*pow(1-t,n-i);
y+=pt[i].y*Cnk(n,i)*pow(t,i)*pow(1-t,n-i);
}
dc.SetPixel(ROUND(x),ROUND(y),RGB(0,0,255)); //曲线颜色}
}
double CDrawYTQXView::Cnk(const int &n, const int &i)//Bernstein 第一项
{
return double(Factorial(n)/(Factorial(i)*Factorial(n-i)));
}
int CDrawYTQXView::Factorial(int m)//阶乘函数
{
int f=1;
for(int i=1;i<=m;i++)
f*=i;
return f;
}
void CDrawYTQXView::DrawB3_curves() //绘制B样条曲线{
CClientDC dc(this);
int i,rate=10,m;
long lx,ly;
m=CtrlPoint-(3+1);
double F03,F13,F23,F33;
lx=ROUND((pt[0].x+4.0*pt[1].x+pt[2].x)/6.0); //t=0的起点x坐标
ly=ROUND((pt[0].y+4.0*pt[1].y+pt[2].y)/6.0);//t=0的起点y坐标
dc.MoveTo(lx,ly);
CPen MyPen2,*pOldPen2;
MyPen2.CreatePen(PS_SOLID,2,RGB(0,0,255)); //颜色设置
pOldPen2=dc.SelectObject(&MyPen2);
for(i=1;i<m+2;i++) //m+1段三次样条曲线
{
for(double t=0;t<=1;t+=1.0/rate)
{
F03=(-t*t*t+3*t*t-3*t+1)/6;//计算F0,3(t)
F13=(3*t*t*t-6*t*t+4)/6;//计算F1,3(t)
F23=(-3*t*t*t+3*t*t+3*t+1)/6;//计算F2,3(t)
F33=t*t*t/6;//计算B3,3(t)
lx=ROUND(pt[i-1].x*F03+pt[i].x*F13+pt[i+1].x*F23+pt[i+2].x*F33 );
ly=ROUND(pt[i-1].y*F03+pt[i].y*F13+pt[i+1].y*F23+pt[i+2].y*F33 );
dc.LineTo(lx,ly);
}
}
dc.SelectObject(pOldPen2);
MyPen2.DeleteObject();
}
void CDrawYTQXView::DrawCharPolygon()//绘制控制多边形
{
CClientDC dc(this);
CPen MyPen,*pOldPen;
MyPen.CreatePen(PS_SOLID,2,RGB(0,0,0)); //控制多边形
pOldPen=dc.SelectObject(&MyPen);
for(int i=0;i<CtrlPoint;i++)
{
if(i==0)
{
dc.MoveTo(pt[i]);
dc.Ellipse(pt[i].x-2,pt[i].y-2,pt[i].x+2,pt[i].y+2);
}
else
{
dc.LineTo(pt[i]);
dc.Ellipse(pt[i].x-2,pt[i].y-2,pt[i].x+2,pt[i].y+2);
}
}
dc.SelectObject(pOldPen);
MyPen.DeleteObject();
}
void CDrawYTQXView::OnLButtonDown(UINT nFlags, CPoint point)//获得屏幕控制点坐标
{
// TODO: Add your message handler code here and/or call default
CView::OnLButtonDown(nFlags, point);
if(Flag)
{
pt[CtrlPoint].x=point.x;
pt[CtrlPoint].y=point.y;
if(CtrlPoint<N_MAX_POINT)
CtrlPoint++;
else
Flag=false;
DrawCharPolygon();
}
else DrawCharPolygon1();
}
void CDrawYTQXView::OnRButtonDown(UINT nFlags, CPoint point)//调用绘制函数
{
// TODO: Add your message handler code here and/or call default
Flag=false;
if(Sign==0)Hermite();
if(Sign==1)DrawBezier();
if(Sign==2)DrawB3_curves();
CView::OnRButtonDown(nFlags, point);
}
四、实验结果
1、绘制Hermite曲线
2、绘制Bezier曲线
3. 绘制B样条曲线
五、心得体会
通过实验进一步学习和了解MFC的菜单的实现及其响应函数的实现,并设置鼠标的左键激活绘制多边形,右键激活绘制Hermite、Bezier、B样条三种曲线。
掌握了三个齐次坐标矩阵以及它们各自点的平移,旋转,缩放,错切变换的坐标矩阵。
再做实验的同时又很好的复习了考试的内容,一举两得!。