




已阅读5页,还剩35页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
基于vc+界面的图形绘制摘要bezier曲线和直线bresenham算法、圆bresenham算法是计算机图形学中最基本、最重要的内容之一,在计算机辅助几何设计领域得到了广泛应用。为使用户直观的了解其几何特性,介绍了在visual c+6.0环境下开发bezier曲线和直线bresenham算法、圆bresenham算法绘制程序的思路和方法,主要探讨了bezier曲线程序开发中遇到的问题。关键词 visual c+6.0,bezier曲线,bresenham算法,绘制,程序开发目录绪论2一、正文3 1.1设计目的3 1.2设计内容3 1.3设计思路4 1.4定义41.4.1 bezier曲线4 1.4.2直线的bresenham算法7 1.4.3圆的bresenham算法8 1.5算法设计81.5.1 bezier曲线8 1.5.2直线的bresenham算法10 1.5.3圆的bresenham算法11 1.6程序运行与结果11 1.6.1 bezier曲线14 1.6.2直线的bresenham算法16 1.6.3圆的bresenham算法17二、设计总结18三、参考文献18附录19附录一 bezier曲线19 附录二 直线的bresenham算法25 附录三 圆的bresenham算法34绪论在计算机发展初期,人们就开始从事计算机图形的开发。直再到计算机硬件软件和计算机图形学高度发达的九十年代,人们发现复杂的数据以视觉的形式表现时是最易理解的,因而图形得以迅猛发展,于是各种图形工具软件包相继推出。visual c+60作为microsoft visual studio开发组件中最为强大的编程工具,其mfc封装了绘图所需的各种操作。因此,本文便是基于visual c+6.0的优点,讲述如何在二维场景中开发bezier曲线和直线bresenham算法、圆bresenham算法绘制程序。一、正文部分1.1 设计目的课程设计是信息与计算科学专业集中实践性环节之一,是学习完计算机图形学课程后进行的一次全面的综合练习。其目的是:要达到理论与实际应用相结合,在掌握图形学的基本原理、算法和实现技术基础上,通过编程实践学会基本的图形软件开发技术。并培养良好的程序设计技能。1.2 设计内容图形通常是由点 、线 、面 、体等几何元素和灰度 、色彩 、线型 、线宽等非几何属性组成 。直线与曲线是组成图形的基本元素 。因此,研究高效、高精度的直线曲线、圆生成算法,对于开发高性能的汁算机数控系统具有十分重要的意义。曲线曲面的表示是计算机图形学的重要内容。它是描述物体的外型。建立所画对象的数学模型的有力工具。在飞机、轮船、汽车的外形设计中,原本一直使用样条曲线,但样条曲线作为设计工具缺少灵活性和直观性,直到bezier曲线的出现,才解决了这些问题。1962年,法国雷诺汽车公司的工程师pebezier构造了一种以逼近为基础的参数曲线和曲面的设计方法以这种方法为主完成了一个称为unisurf的曲线和曲面设计系统并1972年在公司投入使用。bezier方法将函数逼近同几何表示结合起来,使得设计师在工程设计中能比较直观地意识到所给条件与设计出的曲线之间的关系。能方便地通过控制输入参数来改变曲线的形状。bezier曲线具有良好的几何性质,能简洁、完美地描述和表达自由曲线曲面,现在,bezier曲线作为很好的曲线拟合工具,因其具有保凸性,可调控性等特点而被广泛应用于计算机辅助设计(cad)及图像的绘制( 操作系统windows的曲线就是用曲线实现的)。本文主要对bezier的生成算法,构成曲线的性质特点,以及实用问题进行了研究。直线和圆是基本的几何元素。直线生成算法和圆生成算法是计算机图形学的重要基础。是数控机床和快速成型机控制系统中插补算法的数学基础。直线和圆生成算法的好坏不仅直接影响图形生成与显示的效率。而且与数控加工和快速原型制造的速度和精度有直接的关系。因此,研究高效、高精度的直线和圆的生成算法,对于开发高性能的汁算机数控系统具有十分重要的意义。而生成直线和圆的bresenham算法是众多直线和圆生成算法中比较有效的方法。本文用vc+语言编写程序以交互方式在图形绘制区实现直线及圆的bresenham算法和beizer曲线。1.3 设计思路在进行图形绘制时,允许用户选择鼠标拾取或键盘输入控制点,但二者不可在同一条曲线的绘制中交替使用。即图形绘制菜单设置两项子菜单:鼠标点击;键盘输入。对鼠标拾取选项,实行动态显示,即点击鼠标左键确定顶点,右键画图。随着控制顶点数的增加,曲线次数动态增加曲线形状动态改变,特征多边形随顶点动态绘出。对键盘输入选项,采用静态输出,即通过对话框中的编辑框控件输入各控制点的坐标,点击确定后,静态显示图形。因为beizer曲线的控制定点数不确定,坐标输入较麻烦,所以采用鼠标点击;而直线只需知道起点坐标和中点坐标,圆只需知道圆心坐标和半径,所以选择采用键盘输入。1.4 定义1.4.1 bezier曲线bezier曲线是由一组折线集或称之为bezier特征多边形来定义的。曲线的起点和终点分别与该多边形的起点、终点重合,且多边形的第一条边和最后一条边表示了曲线在起点和终点处的切矢量方向。曲线的形状趋于特征多边形的形状。当给定n+1个控制顶点的位置矢量,则bezier曲线可定义为: 其中构成该bezier曲线的特征多边形,为第个阶bernstein基底函数或混合函数:于是bezier曲线有如下特性: 端点性质。每条bezier曲线的起点、终点与相应的特征多边形的起点、终点重合。bezier曲线的起点和终点处的切线方向和特征多边形的第一条边及最后一条边的走向一致。 对称性。若保持原全部顶点的位置不变,只是把次序颠倒过来,则新的bezier曲线与原bezier曲线形状相同,但方向相反。这个性质说明bezier曲线在起点处有什么几何性质,在终点处也有相同的性质。 凸包性。在几何图形上,bezier曲线在中各点是控制点的凸线性组合,即曲线落在构成的凸包之中。 几何不变性。bezier曲线位置与形状与其特征多边形顶点的位置有关,它不依赖坐标系的选择。 变差缩减性。若bezier曲线的特征多边形是一个平面图形,则平面内任意直线与的交点个数不多于该直线与其特征多边形的交点个数。这一性质叫变差缩减性质,它反映了bezier曲线比其特征多边形的波动还小,这也就是说bezier曲线比特征多边形的折线更光滑。 仿射不变形。对于任意的仿射变换a:即在仿射变换下,的形式不变。计算bezier曲线的公式可以用矩阵形式表示,以3次为例:其中b称为bezier矩阵。于是:另外,bezier曲线有两个缺点:一是基底函数的多项式次数由控制顶点的个数来决定,增加一个控制点就得换高一次的函数;二是缺少局部控制,每个控制点的位置都对曲线上的点的位置有影响。1.4.2 直线的bresenham算法(任意斜率)bresenham画线法与中点画线法相似,是计算机图形学领域使用最广泛的直线扫描转换算法,它通过每列象素中确定与理想直线最近的象素来进行直线的扫描的转换的。通过各行,各列的象素中心构造一组虚拟网格线的交点,然后确定该列象素中与此交点最近的的象素。该算法的巧妙之处在于可以采用增量计算,使得对于每一列,只要检查一个误差项的符号,就可以确定该列的所求对象。首先选择像素点,位于右侧的点。直线可表示为方程其中斜率;此处的讨论直线斜率在0到1之间, 每次都增加1个单元,设像素为。下一个像素点坐标为(,),由与及的距离及的大小而定。计算公式为: 如果,则,否则。将计算公式代入,再用同乘等式两边,并以,代入上述等式,得 是用以判断符号的误差。由于在第一象限,总大于0,所以 仍旧可以用做判断符号的误差。为 求误差的初值,可将和代入中的,而得到:1.4.3 圆的bresenham算法(任意中点,任意半径)本算法采用与bresenham直线转换法相同的策略。我们从位于的像素开始,以一次一个像素的方式向右推进直至。由于这个八分圆的走向被限制在水平线与向下的斜线之间,我们在每一步的候选对象就只有右边的像素t和右下方的像素s。只要画出圆上的弧,根据圆的对称性,即可画出整个圆。1.5 算法设计1.5.1 bezier曲线 本次程序开发的重点是要实现bezier曲线的动态绘制,由于基函数随控制顶点的增加而改变,根据bezier曲线定义先给出函数流程图。如图1所示:结束,返回主程序由主程序代入曲线次数ni=0i 1000#pragma once#endif / _msc_ver 1000class cbezierview : public cviewprotected: / create from serialization onlycbezierview();declare_dyncreate(cbezierview)public:cbezierdoc* getdocument();public:public:virtual void ondraw(cdc* pdc); / overridden to draw this viewvirtual bool precreatewindow(createstruct& cs);protected:virtual bool onprepareprinting(cprintinfo* pinfo);virtual void onbeginprinting(cdc* pdc, cprintinfo* pinfo);virtual void onendprinting(cdc* pdc, cprintinfo* pinfo);public:void drawbezier();double cnk(const int& n,const int& i);int factorial(int m);void drawcharpolygon();virtual cbezierview();#ifdef _debugvirtual void assertvalid() const;virtual void dump(cdumpcontext& dc) const;#endifprotected:bool flag;cpoint *pt;int ctrlpoint;protected:afx_msg void onmenubezier();afx_msg void onlbuttondown(uint nflags, cpoint point);afx_msg void onrbuttondown(uint nflags, cpoint point);declare_message_map();#ifndef _debug / debug version in bezierview.cppinline cbezierdoc* cbezierview:getdocument() return (cbezierdoc*)m_pdocument; #endif2. bezierview.cpp#include stdafx.h#include bezier.h#includemath.h#define round(a) int(a+0.5)#define n_max_point 10#include bezierdoc.h#include bezierview.h#ifdef _debug#define new debug_new#undef this_filestatic char this_file = _file_;#endifimplement_dyncreate(cbezierview, cview)begin_message_map(cbezierview, cview)on_command(id_menubezier, onmenubezier)on_wm_lbuttondown()on_wm_rbuttondown()on_command(id_file_print, cview:onfileprint)on_command(id_file_print_direct, cview:onfileprint)on_command(id_file_print_preview, cview:onfileprintpreview)end_message_map()cbezierview:cbezierview() flag=false; cbezierview:cbezierview() bool cbezierview:precreatewindow(createstruct& cs)return cview:precreatewindow(cs); void cbezierview:ondraw(cdc* pdc)cbezierdoc* pdoc = getdocument();assert_valid(pdoc);bool cbezierview:onprepareprinting(cprintinfo* pinfo) return doprepareprinting(pinfo); void cbezierview:onbeginprinting(cdc* /*pdc*/, cprintinfo* /*pinfo*/) void cbezierview:onendprinting(cdc* /*pdc*/, cprintinfo* /*pinfo*/) #ifdef _debugvoid cbezierview:assertvalid() constcview:assertvalid(); void cbezierview:dump(cdumpcontext& dc) constcview:dump(dc); cbezierdoc* cbezierview:getdocument() / non-debug version is inlineassert(m_pdocument-iskindof(runtime_class(cbezierdoc);return (cbezierdoc*)m_pdocument;#endif /_debugvoid cbezierview:drawcharpolygon()cclientdc dc(this);cpen mypen,*oldpen;mypen.createpen(ps_solid,3,rgb(0,0,0);/控制多边形oldpen=dc.selectobject(&mypen);for(int i=0;ictrlpoint;i+)if(i=0)dc.moveto(pti);dc.ellipse(pti.x-2,pti.y-2,pti.x+2,pti.y+2);elsedc.lineto(pti);dc.ellipse(pti.x-2,pti.y-2,pti.x+2,pti.y+2);dc.selectobject(oldpen);mypen.deleteobject();int cbezierview:factorial(int m)/阶乘函数int f=1;for(int i=1;i=m;i+)f*=i;return f;double cbezierview:cnk(const int &n, const int &i)/计算bernstein第一项函数return double(factorial(n)/(factorial(i)*factorial(n-i);void cbezierview:drawbezier()cclientdc dc(this);double x,y;int rate=800,n;n=ctrlpoint-1;for(double t=0;t=1;t+=1.0/rate)x=0;y=0;for(int i=0;isetwindowtext(曲线与曲面:bezier曲线);messagebox(欢迎来到bezier曲线绘制窗口!单击鼠标左键绘制控制多边形,单击鼠标右键绘制曲线,提示,mb_ok);pt=new cpointn_max_point;flag=true;ctrlpoint=0;void cbezierview:onlbuttondown(uint nflags, cpoint point) cview:onlbuttondown(nflags, point);if(flag)ptctrlpoint.x=point.x;ptctrlpoint.y=point.y;if(ctrlpoint 1000#pragma once#endif / _msc_ver 1000#includeinputdlg.hclass cbresenhamview : public cviewprotected: / create from serialization onlycbresenhamview();declare_dyncreate(cbresenhamview)public:cbresenhamdoc* getdocument();public:void mbline();public:virtual void ondraw(cdc* pdc); / overridden to draw this viewvirtual bool precreatewindow(createstruct& cs);protected:virtual bool onprepareprinting(cprintinfo* pinfo);virtual void onbeginprinting(cdc* pdc, cprintinfo* pinfo);virtual void onendprinting(cdc* pdc, cprintinfo* pinfo);public:void swap(double &,double &);virtual cbresenhamview();#ifdef _debugvirtual void assertvalid() const;virtual void dump(cdumpcontext& dc) const;#endifprotected: double x1,x2,y1,y2;protected:afx_msg void onmenumbline();declare_message_map();#ifndef _debug / debug version in bresenhamview.cppinline cbresenhamdoc* cbresenhamview:getdocument() return (cbresenhamdoc*)m_pdocument; #endif2. bresenhamview.cpp#include stdafx.h#include bresenham.h#include bresenhamdoc.h#include bresenhamview.h#define round(a) int (a+0.5)#ifdef _debug#define new debug_new#undef this_filestatic char this_file = _file_;#endifimplement_dyncreate(cbresenhamview, cview)begin_message_map(cbresenhamview, cview)on_command(id_menumbline, onmenumbline)on_command(id_file_print, cview:onfileprint)on_command(id_file_print_direct, cview:onfileprint)on_command(id_file_print_preview, cview:onfileprintpreview)end_message_map()cbresenhamview:cbresenhamview() cbresenhamview:cbresenhamview()bool cbresenhamview:precreatewindow(createstruct& cs) return cview:precreatewindow(cs); void cbresenhamview:ondraw(cdc* pdc)cbresenhamdoc* pdoc = getdocument();assert_valid(pdoc);bool cbresenhamview:onprepareprinting(cprintinfo* pinfo)return doprepareprinting(pinfo); void cbresenhamview:onbeginprinting(cdc* /*pdc*/, cprintinfo* /*pinfo*/) void cbresenhamview:onendprinting(cdc* /*pdc*/, cprintinfo* /*pinfo*/) #ifdef _debugvoid cbresenhamview:assertvalid() constcview:assertvalid(); void cbresenhamview:dump(cdumpcontext& dc) const cview:dump(dc); cbresenhamdoc* cbresenhamview:getdocument() / non-debug version is inlineassert(m_pdocument-iskindof(runtime_class(cbresenhamdoc);return (cbresenhamdoc*)m_pdocument;#endif void cbresenhamview:mbline()cclientdc dc(this);colorref rgb=rgb(0,0,255);if(x2x1) swap(x2,x1); swap(y2,y1); /画第一个点 double x,y; x=x1; y=y1; dc.setpixel(round(x),round(y),rgb); /首先处理直线平行坐标轴 if(y1=y2) /平行x轴 while(xx2) x-; dc.setpixel(round(x),round(y),rgb); return ; if(x1=x2) /平行y轴 while (yy2) y-; dc.setpixel(round(x),round(y),rgb); return ; double dx=x2-x1,dy=y2-y1; double p; double twody=2*dy,twominusdx=2*(dy-dx),twodx=2*dx,twominusdy=2*(dx-dy); double twosum=2*(dy+dx); double k=(double)dy / (double)dx; /0k1的情况 if(k0.0) p=2*dy-dx; while(xx2) x+; if(p=1的情况 if(k=1.0) p=dy; while(yy2) y+; if(pk-1的情况 if(k-1&k0) p=2*dy+dx; while(x=0) p+=twody; else y-; p+=twosum; dc.setpixel(round(x),round(y),rgb); /k-1的情况 if(ky2) y-; if(p=0) p-=twodx; else x+; p-=twosum; dc.setpixel(round(x),round(y),rgb); void cbresenhamview:onmenumbline() messagebox(欢迎来到直线bresenham算法,请在接下来的窗口中输入直线的两端点,你就可以得到你想要的直线,提示,mb_ok);inputdlg dlg;if(dlg.domodal()=idok)x1=dlg.m_x1;x2=dlg.m_x2;y1=dlg.m_y1;y2=dlg.m_y2;afxgetmainwnd()-setwindowtext(基本图形扫描转换:mbline);redrawwindow();mbline();void cbresenhamview:swap(double &a, double &b) double t=a;a=b;b=t; 附录三 圆的bresenham程序代码及绘制1. circleview.h#if !defined(afx_circleview.hcircleview.hcircleview_h_3c0f4c32_80c0_4cfa_8a7b_3fc43e4c4747_included_)#define afx_circleview_h_3c0f4c32_80c0_4cfa_8a7b_3fc43e4c4747_includ_#if _msc_ver 1000#pragma once#endif / _msc_ver 1000#includeinputdlg.class ccircleview : public cviewprotected:ccircleview();declare_dyncreate(ccircleview)public:ccircledoc* getdocument();public:void circlepoint(double x,double y);void mcircle();public:virtual void ondraw(cdc* pdc); / overridden to draw this viewvirtual bool precreatewindow(createstruct& cs);protected:virtual bool onprepareprinting(cprintinfo* pinfo);virtual void onbeginprinting(cdc* pdc, cprintinfo* pinfo);virtual void onendprinting(cdc* pdc, cprintinfo* pinfo);public:virtual ccircleview();#ifdef _debugvirtual void assertvalid() const;virtual void dump(cdumpcontext& dc) const;#endifprotected:double r;int x,y;protected:afx_msg void onmenumcircle();declare_message_map();#ifndef _d
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 1.2走向共同富裕 课件 2025-2026学年度道德与法治九年级上册 统编版
- 象棋学习课件
- 豌豆种植科学课件
- 2025版厦门市区婚姻解除财产分配及子女抚养监护合同
- 2025版智慧家居产业财务顾问及市场拓展合同
- 2025版建筑节能材料研发与应用劳务分包合同范本
- 2025年度商务会议场地及专业设备租赁服务合同
- 2025年度大型会展活动策划合同
- 2025版外卖配送服务合同综合管理范本
- 2025版全新真石漆外墙施工及维护一体化合同
- 驾驶员安全教育培训考试试卷含答案
- 污水处理站运行记录台账范本
- 2025年消毒供应室业务学习考试试题(附答案)
- 校园基孔肯雅热防控措施课件
- 图像特征提取讲解
- 国家电网公司招聘高校毕业生应聘登记表
- GA 1801.4-2022国家战略储备库反恐怖防范要求第4部分:火炸药库
- 消化道出血的内镜治疗
- GB/T 4623-2006环形混凝土电杆
- GB/T 36572-2018电力监控系统网络安全防护导则
- 甲状腺危象教学课件
评论
0/150
提交评论