实验三:圆的生成算法

3.1实验目的

(1)了解DDA算法、中点画圆法、Bresenham算法
(2)掌握VC++中CDC类的用法

3.2实验内容

(1)类的编写
(2)完成DDA算法、中点画圆法、Bresenham算法

3.3算法思路

在平面解析几何中,圆的方程可以描述为(x–x0)2+(y–y0)2=R2,其中(x0,y0)是圆心坐标,R是圆的半径,特别的,当(x0,y0)就是坐标中心点时,圆方程可以简化为x2+y2=R2。在计算机图形学中,圆和直线一样,也存在点阵输出设备上显示或输出的问题,因此也需要一套光栅扫描转换算法。为了简化,我们先考虑圆心在原点的圆的生成,对于中心不是原点的圆,可以通过坐标的平移变换获得相应位置的圆。
在进行扫描转换之前,需要了解一个圆的特性,就是圆的八分对成性。如下图所示:
圆心位于原点的圆有四条对称轴x=0、y=0、x=y和x=-y,若已知圆弧上一点P(x,y),就可以得到其关于四条对称轴的七个对称点:(x,-y)、(-x,y)、(-x,-y)、(y,x)、(y,-x)、(-y,x)、(-y,-x),这种性质称为八分对称性。因此只要能画出八分之一的圆弧,就可以利用对称性的原理得到整个圆。
有几种较容易的方法可以得到圆的扫描转换,首先介绍一下直角坐标法。已知圆方程:x2+y2=R2,若取x作为自变量,解出y。
在生成圆时先扫描转换四分之一的圆周,让自变量x从0到R以单位步长增加,在每一步时可解出y,然后调用画点函数即可逐点画出圆。但这样做,由于有乘方和平方根运算,并且都是浮点运算,算法效率不高。而且当x接近R值时(圆心在原点),在圆周上的点(R,0)附近,由于圆的斜率趋于无穷大,因浮点数取整需要四舍五入的缘故,使得圆周上有较大的间隙。接下来介绍一下极坐标法,假设直角坐标系上圆弧上一点P(x,y)与x轴的夹角是θ,则圆的极坐标方程为:
x=Rcosθ
y=Rsinθ
生成圆是利用圆的八分对称性,使自变量θ的取值范围为(0,45°)就可以画出整圆。
(1)角度数值微分法(DDA法):
直角坐标系的圆的参数方程为:
{█(x=x0+Rcosθ@y=y0+Rsinθ)┤
由上式导出
x-xc=-Rsinθdθ
y-yc=Rcosθdθ
当x-xc从-r到r做加1递增时,就可以求出对应的圆周点的y坐标。但是这样求出的圆周上的点是不均匀的,| x-xc | 越大,对应生成圆周点之间的圆周距离也就越长。因此,所生成的圆不美观。
(2)中点画圆法:
考虑圆心在原点,半径为R的圆在第一象限内的八分之一圆弧,从点(0,R)到点(R/,R/)顺时针方向确定这段圆弧。假定某点Pi(xi,yi)已经是该圆弧上最接近实际圆弧的点,那么Pi的下一个点只可能是正右方的P1或右下方的P2两者之一,如下图所示:
构造判别函数:
F(x,y)=x2+y2–R2
当F(x,y)=0,表示点在圆上,当F(x,y)>0,表示点在圆外,当F(x,y)<0,表示点在圆内。如果M是P1和P2的中点,则M的坐标是(xi+1,yi–0.5),当F(xi+1,yi–0.5)<0时,M点在圆内,说明P1点离实际圆弧更近,应该取P1作为圆的下一个点。同理分析,当F(xi+1,yi–0.5)>0时,P2离实际圆弧更近,应取P2作为下一个点。当F(xi+1,yi–0.5)=0时,P1和P2都可以作为圆的下一个点,算法约定取P2作为下一个点。
(3)Bresenham画圆算法:
如果能将判别式规约到整数运算,则可以简化计算,提高效率。于是人们针对中点画圆法进行了多种改进,其中一种方式是将d的初始值由1.25–R改成1–R,考虑到圆的半径R总是大于2,因此这个修改不会响d的初始值的符号,同时可以避免浮点运算。还有一种方法是将d的计算放大两倍,同时将初始值改成3–2R,这样避免了浮点运算,乘二运算也可以用移位快速代替,采用3–2R为初始值的改进算法,又称为Bresenham算法。

3.4流程图

(1)角度数值微分法(DDA法):
(2)中点画圆法:
(3)Bresenham画圆算法:

3.5实验步骤

(1)角度数值微分法(DDA法):
直角坐标系的圆的参数方程为:
{█(x=x0+Rcosθ@y=y0+Rsinθ)┤
由上式导出
x-xc=-Rsinθdθ
y-yc=Rcosθdθ
推导:
xn+1=xn-(yn-y0)dθ
yn+1=yn-(xn-x0)dθ
(2)中点画圆法:
1)构造判别函数:F(x,y)=x2+y2–R2。
当F(x,y)=0,表示点在圆上,当F(x,y)>0,表示点在圆外,当F(x,y)<0,表示点在圆内。
如果M是P1和P2的中点,则M的坐标是(xi+1,yi–0.5),当F(xi+1,yi–0.5)<0时,M点在圆内,说明P1点离实际圆弧更近,应该取P1作为圆的下一个点。
同理分析,当F(xi+1,yi–0.5)>0时,P2离实际圆弧更近,应取P2作为下一个点。当F(xi+1,yi–0.5)=0时,P1和P2都可以作为圆的下一个点,算法约定取P2作为下一个点。
2)将M点坐标(xi+1,yi–0.5)带入判别函数F(x,y),得到判别式d:
d=F(xi+1,yi–0.5)=(xi+1)2+(yi–0.5)2–R2
3)若d<0,则取P1为下一个点,此时P1的下一个点的判别式为:
d’=F(xi+2,yi–0.5)=(xi+2)2+(yi–0.5)2–R2
展开后将d带入可得到判别式的递推关系:
d’=d+2xi+3
若d>0,则取P2为下一个点,此时P2的下一个点的判别式为:
d’=F(xi+2,yi–1.5)=(xi+2)2+(yi–1.5)2–R2
展开后将d带入可得到判别式的递推关系:
d’=d+2(xi-yi)+5
4)特别的,在第一个象限的第一个点(0,R)时,可以推倒出判别式d的初始值d0:
d0=F(1,R–0.5)=1–(R–0.5)2–R2=1.25-R
考虑到圆心不在原点的情况,需要对计算出来的坐标进行平移。
(3)Bresenham画圆算法:
1)构造判别函数:F(x,y)=x2+y2–R2。
当F(x,y)=0,表示点在圆上,当F(x,y)>0,表示点在圆外,当F(x,y)<0,表示点在圆内。
如果M是P1和P2的中点,则M的坐标是(xi+1,yi–0.5),当F(xi+1,yi–0.5)<0时,M点在圆内,说明P1点离实际圆弧更近,应该取P1作为圆的下一个点。
同理分析,当F(xi+1,yi–0.5)>0时,P2离实际圆弧更近,应取P2作为下一个点。当F(xi+1,yi–0.5)=0时,P1和P2都可以作为圆的下一个点,算法约定取P2作为下一个点。
2)将M点坐标(xi+1,yi–0.5)带入判别函数F(x,y),得到判别式d:
d=F(xi+1,yi–0.5)=(xi+1)2+(yi–0.5)2–R2
3)若d<0,则取P1为下一个点,此时P1的下一个点的判别式为:
d’=F(xi+2,yi–0.5)=(xi+2)2+(yi–0.5)2–R2
展开后将d带入可得到判别式的递推关系:
d’=d+4xi+6
若d>0,则取P2为下一个点,此时P2的下一个点的判别式为:
d’=F(xi+2,yi–1.5)=(xi+2)2+(yi–1.5)2–R2
展开后将d带入可得到判别式的递推关系:
d’=d+4(xi-yi)+10
4)特别的,在第一个象限的第一个点(0,R)时,可以推倒出判别式d的初始值d0:
d0=F(1,R–0.5)=1–(R–0.5)2–R2=3-2R
考虑到圆心不在原点的情况,需要对计算出来的坐标进行平移。

3.6实验代码

(1)角度DDA圆生成算法

/
//角度DDA圆生成算法
/
void CLiHuchenView::OnDdacircle()
{// TODO: Add your command handler code hereCDC *pDC=GetDC();//获取设备指针int xc=200,yc=200,r=50,c=RGB(0,0,255);///定义圆心,角度,半径,圆的颜色蓝色int x=0,y=r,n=r; //赋初值double rc = (double)r; //修改类型double z=1.0/rc; //得到微分角度double a=x,b=y; //将x,y分别赋予a,bdouble tmp; //定义变量while(n > 0){//八个区域点,画点pDC->SetPixel((xc+x),(yc+y),c);//(x,y)pDC->SetPixel((xc-x),(yc+y),c);//(-x,y)pDC->SetPixel((xc+x),(yc-y),c);//(x,-y)pDC->SetPixel((xc-x),(yc-y),c);//(-x,-y)pDC->SetPixel((xc+y),(yc+x),c);//(y,x)pDC->SetPixel((xc-y),(yc+x),c);//(-y,x)pDC->SetPixel((xc+y),(yc-x),c);//(y,-x)pDC->SetPixel((xc-y),(yc-x),c);//(-y,-x)tmp=a;a-=b*z; //计算下一点横坐标b+=tmp*z; //计算下一点纵坐标x = (int)(a);y = (int)(b);n--;}if(x == y){//八个区域点,画点pDC->SetPixel((xc+x),(yc+y),c);//(x,y)pDC->SetPixel((xc-x),(yc+y),c);//(-x,y)pDC->SetPixel((xc+x),(yc-y),c);//(x,-y)pDC->SetPixel((xc-x),(yc-y),c);//(-x,-y)pDC->SetPixel((xc+y),(yc+x),c);//(y,x)pDC->SetPixel((xc-y),(yc+x),c);//(-y,x)pDC->SetPixel((xc+y),(yc-x),c);//(y,-x)pDC->SetPixel((xc-y),(yc-x),c);//(-y,-x)}ReleaseDC(pDC);//指针释放
}

(2)中点圆生成算法:

/
//中点圆生成算法
/
void CLiHuchenView::OnMidpointcircle()
{// TODO: Add your command handler code hereCDC *pDC=GetDC();//获取设备指针int xc=300,yc=300,r=50,c=RGB(255,0,0);///定义圆心,半径,圆的颜色红色int x,y;//定义变量x,yfloat d;//定义中点带入圆的值dx=0;y=r;d=1.25-r;//赋初值//八个区域点,画点pDC->SetPixel((xc+x),(yc+y),c);//(x,y)pDC->SetPixel((xc-x),(yc+y),c);//(-x,y)pDC->SetPixel((xc+x),(yc-y),c);//(x,-y)pDC->SetPixel((xc-x),(yc-y),c);//(-x,-y)pDC->SetPixel((xc+y),(yc+x),c);//(y,x)pDC->SetPixel((xc-y),(yc+x),c);//(-y,x)pDC->SetPixel((xc+y),(yc-x),c);//(y,-x)pDC->SetPixel((xc-y),(yc-x),c);//(-y,-x)//画圆while(x<=y){//判断d的正负if(d<0){d+=2*x+3;}else{d+=2*(x-y)+5;y--;}x++;pDC->SetPixel((xc+x),(yc+y),c);//(x,y)pDC->SetPixel((xc-x),(yc+y),c);//(-x,y)pDC->SetPixel((xc+x),(yc-y),c);//(x,-y)pDC->SetPixel((xc-x),(yc-y),c);//(-x,-y)pDC->SetPixel((xc+y),(yc+x),c);//(y,x)pDC->SetPixel((xc-y),(yc+x),c);//(-y,x)pDC->SetPixel((xc+y),(yc-x),c);//(y,-x)pDC->SetPixel((xc-y),(yc-x),c);//(-y,-x)}ReleaseDC(pDC);//指针释放
}

(3)Bresenham圆生成算法:

/
//Bresenham圆生成算法
/
void CLiHuchenView::OnBresenhamcircle()
{// TODO: Add your command handler code hereCDC *pDC=GetDC();//获取设备指针int xc=100,yc=100,r=50,c=RGB(0,255,0);///定义圆心,半径,圆的颜色绿色int x=0,y=r,p=3-2*r;//赋初值//画圆while(x<y){//八个区域点,画点pDC->SetPixel((xc+x),(yc+y),c);//(x,y)pDC->SetPixel((xc-x),(yc+y),c);//(-x,y)pDC->SetPixel((xc+x),(yc-y),c);//(x,-y)pDC->SetPixel((xc-x),(yc-y),c);//(-x,-y)pDC->SetPixel((xc+y),(yc+x),c);//(y,x)pDC->SetPixel((xc-y),(yc+x),c);//(-y,x)pDC->SetPixel((xc+y),(yc-x),c);//(y,-x)pDC->SetPixel((xc-y),(yc-x),c);//(-y,-x)//判断p的正负if(p<0){p+=4*x+6;}else{p+=4*(x-y)+10;y--;}x++;if(x==y)pDC->SetPixel((xc+x),(yc+y),c);//(x,y)pDC->SetPixel((xc-x),(yc+y),c);//(-x,y)pDC->SetPixel((xc+x),(yc-y),c);//(x,-y)pDC->SetPixel((xc-x),(yc-y),c);//(-x,-y)pDC->SetPixel((xc+y),(yc+x),c);//(y,x)pDC->SetPixel((xc-y),(yc+x),c);//(-y,x)pDC->SetPixel((xc+y),(yc-x),c);//(y,-x)pDC->SetPixel((xc-y),(yc-x),c);//(-y,-x)}ReleaseDC(pDC);//指针释放
}

3.7实验结果展示

红色:中点画线算法
绿色: Bresenham算法
蓝色:角度微分法(DDA法)

计算机图形学(三)——实验三:圆的生成算法相关推荐

  1. 《计算机图形学》实验报告 Cohen Sutherland裁剪算法

    一.实验目的和要求 熟悉光栅图形学中的相关直线段裁剪算法.理解Cohen-Sutherland裁剪算法. 二.实验内容 实现Cohen-Sutherland编码线段裁剪算法,能看到裁剪前后的屏幕显示效 ...

  2. 【XJTUSE计算机图形学】第三章 几何造型技术(1)——参数曲线和曲面

    文章目录 [XJTUSE计算机图形学]第三章 几何造型技术(1)--参数曲线和曲面 参数曲线和曲面 曲线曲面参数表示 非参数表示 参数表示 曲线的基本概念 插值.拟合和光顺(掌握概念) 参数化 概念 ...

  3. 【XJTUSE计算机图形学】第三章 几何造型技术(2)——Bezier 曲线与曲面

    文章目录 [XJTUSE计算机图形学]第三章 几何造型技术(2)--Bezier 曲线与曲面 Bezier 曲线与曲面 Bezier 曲线的定义与性质 定义 习题 Bernstein基函数性质 Bez ...

  4. 计算机图形学三维变换论文,计算机图形学 第5章 三维图形生成和变换技术

    计算机图形学 第5章 三维图形生成和变换技术 (63页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 19.90 积分 第五章 目录第五章 三维图形生成和变 ...

  5. c语言计算机图形来画八分画圆,计算机图形学:中点画圆算法

    在平面解析几何中,圆的方程可以描述为(x – x0)2 + (y – y0)2 = R2,其中(x0, y0)是圆心坐标,R是圆的半径,特别的,当(x0, y0)就是坐标中心点时,圆方程可以简化为x2 ...

  6. 计算机图形Opengl的实验报告,计算机图形学OpenGL实验四.doc

    计算机图形学OpenGL实验四 实验报告 学院(系)名称: 姓名学号专业班级实验项目实验四:场景漫游课程名称计算机图形学课程代码实验时间实验地点批改意见成绩教师签字:实验环境(软.硬件环境) 实验目的 ...

  7. 计算机图形学 顶点定义_在计算机图形学中定义一个圆

    计算机图形学 顶点定义 After studying the implementation of lines in computer graphics, we will now be dealing ...

  8. java画bezier曲面_计算机图形学上机实验4-实现Bezier曲线和Bezier曲面的绘制

    <计算机图形学上机实验4-实现Bezier曲线和Bezier曲面的绘制>由会员分享,可在线阅读,更多相关<计算机图形学上机实验4-实现Bezier曲线和Bezier曲面的绘制(9页珍 ...

  9. 计算机地图制图原理与算法,计算机地图制图原理与方法-基本图形生成算法.ppt...

    <计算机地图制图原理与方法-基本图形生成算法.ppt>由会员分享,可在线阅读,更多相关<计算机地图制图原理与方法-基本图形生成算法.ppt(35页珍藏版)>请在人人文库网上搜索 ...

  10. 计算机组成原理_实验三:主存储器原理实验

    实 验 报 告 课程名称:计算机组成原理物理实验 实验项目:主存储器原理实验 实验仪器:数据通路板.控制信号板 一.(PC)→ R2 1. ( PC ) → BUS PC - BUS 2. BUS → ...

最新文章

  1. SP5971 LCMSUM
  2. zencart 1.5.4 安装问题
  3. Linux目录结构FHS
  4. matlab高中必修三数学模拟,基于MATLAB的模拟调制实验报告
  5. 『中级篇』Docker Cloud自动构建 Docker image(55)
  6. linux退出编辑器命令,LINUX中,Vi编辑器的几种模式及保存、退出等命令
  7. Eclipse C/C++开发环境搭建
  8. Android官方开发文档Training系列课程中文版:手势处理之滚动动画及Scroller
  9. Hi3798M V200 SDK文档介绍
  10. golang flag.Parse包
  11. 5v继电器模块实物接线_电气工程师都收藏的西门子S71200PLC接线图设计大全
  12. 10.10做题——USACO1.2/洛谷1207回文平方数(Dual Palindromes)
  13. Microsoft Edge 浏览器如何打开Axure RP文件
  14. python中ctype的应用,协议解析,C语言与python的完美映射,结构体与字符串的相互转换
  15. 用Photoshop制作印章
  16. 11万多职场文章技巧ACCESS数据库
  17. 面向对象期末第三阶段
  18. 逻辑回归(Logistic Regression)
  19. Tengine-Kit人脸检测及关键点
  20. 反驳生命的起点是rna_生命起源之谜:RNA世界假说将迎来终结?

热门文章

  1. mybatis关于factorybean疑问
  2. java怎么设计一个系统吗_谁能帮我设计一个Java的文件管理系统谢谢各位
  3. python小结_Python小结
  4. VMware15下安装Ubuntu18.04
  5. 动态规划算法实验报告_动态规划与中心扩展算法
  6. 如何救队友_PS4《高达EXVSMBON》:如何违抗拥有巴力的他?
  7. mysql8连接 2002_ERROR 2002 mysql连接失败 解决方法
  8. linux快速删除大文件rsync,(总结)Linux下使用rsync最快速删除海量文件的方法
  9. System.IndexOutOfRangeException: 无法找到表 0解决办法
  10. 线性代数【一】:行列式的概念与计算