计算机图形学实习教程之基本图形的生成(直线DDA算法,直线中点算法,Bresenham画圆算法),利用C#实现,附源码
环境:Win10+Visual Studio 2022 Community
在本次实验中需要用到上一篇文章实验内容的代码及环境,详情请见:传送门
目录
一、实验目的
二、实验过程
1.生成直线的DDA算法
2.生成直线的中点算法
3.生成圆的Bresenham算法
一、实验目的
1.熟练掌握生成直线的DDA算法
2.熟练掌握生成直线的中点算法
3.熟练掌握生成圆的Bresenham算法
二、实验过程
1.生成直线的DDA算法
(1)利用已经建立好的DDA直线操作框架,用DDA算法生成直线函数替换系统提供的画线函数g.DrawLine
private void Form1_MouseClick(object sender, MouseEventArgs e)
{Graphics g = CreateGraphics(); //创建图形设备Pen MyPen = new Pen(Color.Red, 1);if (MenuID == 1){if (PressNum == 0) //第一点,保留{FirstX = e.X;FirstY = e.Y;OldX = e.X;OldY = e.Y;}else //第二点,画线{DDALine1(FirstX, FirstY, e.X, e.Y);}PressNum++;if (PressNum >= 2){PressNum = 0; //画线完毕,清零,为画下一条线做准备}}
}
(2)建立DDALine1函数实现DDA直线算法
private void DDALine1(int x0, int y0, int x1, int y1){int x, flag;float m, y;Graphics g = CreateGraphics(); //创建图形设备if (x0 == x1 && y0 == y1) return; //端点重叠,不画。这种情况不可忽略,否则程序有缺陷if (x0 == x1) //垂直线{if (y0 > y1) //保证y0为最小{x = y0;y0 = y1;y1 = x;}for (x = y0; x <= y1; x++){g.DrawRectangle(Pens.Red, x1, x, 1, 1); //画点函数,在(x1,x)处画红点}return;}if (y0 == y1) //水平线{if (x0 > x1){x = x0; x0 = x1; x1 = x;}for (x = x0; x <= x1; x++){g.DrawRectangle(Pens.Red, x, y0, 1, 1);}return;}if (x0 > x1) //按照算法,(x0,y0)是左端点。如果不满足,就将(x0,y0)、(x1,y1)互换{x = x0; x0 = x1; x1 = x;x = y0; y0 = y1; y1 = x;}flag = 0; //记录线段种类if (x1 - x0 > y1 - y0 && y1 - y0 > 0) flag = 1; //第一种线段,不做转化工作if (x1 - x0 > y0 - y1 && y0 - y1 > 0) //第二种线段,转化{flag = 2;y0 = -y0;y1 = -y1; //关于X轴对称,图形点Y坐标加负号}if (y1 - y0 > x1 - x0) //第三种线段,关于y=x对称,图形点坐标x,y互换位置{flag = 3;x = x0; x0 = y0; y0 = x;x = x1; x1 = y1; y1 = x;}if (y0 - y1 > x1 - x0) //第四种线段转化为第一种线段{flag = 4;x = x0; x0 = -y0; y0 = x;x = x1; x1 = -y1; y1 = x;}m = (float)(y1 - y0) / (float)(x1 - x0);for (x = x0, y = (float)y0; x <= x1; x++, y += m){if (flag == 1) g.DrawRectangle(Pens.Red, x, (int)(y + 0.5), 1, 1);if (flag == 2) g.DrawRectangle(Pens.Red, x, -(int)(y + 0.5), 1, 1);if (flag == 3) g.DrawRectangle(Pens.Red, (int)(y + 0.5), x, 1, 1);if (flag == 3) g.DrawRectangle(Pens.Red, (int)(y + 0.5), -x, 1, 1);}}
(3)运行结果
2.生成直线的中点算法
(1)在Form1. cs[设计]页面中,点击、展开菜单项“基本图形生成”,选中子菜单项“中点直线”,并将子菜单项“中点直线”的Name属性值改为"MidLine"
(2)双击“中点直线”菜单项,系统自动建立菜单响应函数MidLine_Click,在该函数中插入如下语句
private void MidLine_Click(object sender, EventArgs e){MenuID = 2; PressNum = 0;Graphics g = CreateGraphics(); //创建图形设备g.Clear(BackColor1); //设置背景色}
(3)因为中点直线的操作方法与DDA直线操作方法完全一样,因此只要能够对两者加以区分,就可以借用DDA直线鼠标操作实现程序部分。为此,做如下修改
private void Form1_MouseClick(object sender, MouseEventArgs e){Graphics g = CreateGraphics(); //创建图形设备Pen MyPen = new Pen(Color.Red, 1);if (MenuID == 1 || MenuID == 2){if (PressNum == 0) //第一点,保留{FirstX = e.X;FirstY = e.Y;OldX = e.X;OldY = e.Y;}else //第二点,画线{if (MenuID == 1)DDALine1(FirstX, FirstY, e.X, e.Y);if (MenuID == 2)MidLine1(FirstX, FirstY, e.X, e.Y);}PressNum++;if (PressNum >= 2){PressNum = 0; //画线完毕,清零,为画下一条线做准备}}}private void Form1_MouseMove(object sender, MouseEventArgs e){Graphics g = CreateGraphics(); //创建图形设备Pen BackPen = new Pen(BackColor1, 1);Pen MyPen = new Pen(ForeColor1, 1);if ((MenuID == 1 || MenuID == 2) && PressNum == 1){if (!(e.X == OldX && e.Y == OldY)){g.DrawLine(BackPen, FirstX, FirstY, OldX, OldY);g.DrawLine(MyPen, FirstX, FirstY, e.X, e.Y);OldX = e.X;OldY = e.Y;}}}
(4)建立MidLine1函数实现中点直线算法
private void MidLine1(int x0, int y0, int x1, int y1){int x, y, d, flag;Graphics g = CreateGraphics(); //创建图形设备if (x0 == x1 && y0 == y1) return; //端点重叠,不画if (x0 == x1) //垂直线{if (y0 > y1){x = y0;y0 = y1;y1 = x;}for (y = y0; y <= y1; y++){g.DrawRectangle(Pens.Red, x1, y, 1, 1); //画点函数,在(x1,y)处画红点}return;}if (y0 == y1) //水平线{if (x0 > x1){x = x0; x0 = x1; x1 = x;}for (x = x0; x <= x1; x++){g.DrawRectangle(Pens.Red, x, y0, 1, 1);//画点函数,在(x,y0)处画红点}return;}if (x0 > x1) //起点(x0,y0)是左端点,如果不满足,就将(x0,y0)、(x1,y1)互换{x = x0; x0 = x1; x1 = x;x = y0; y0 = y1; y1 = x;}flag = 0; //直线类别标记if (x1 - x0 > y1 - y0 && y1 - y0 > 0) flag = 1; //第一种线段,不做转化工作if (x1 - x0 > y0 - y1 && y0 - y1 > 0) //第二种线段转化为第一种线段{flag = 2;y0 = -y0;y1 = -y1;}if (y1 - y0 > x1 - x0) //第三种线段转化为第一种线段{flag = 3;x = x0; x0 = y0; y0 = x;x = x1; x1 = y1; y1 = x;}if (y0 - y1 > x1 - x0) //第四种线段转化为第一种线段{flag = 4;x = x0; x0 = -y0; y0 = x;x = x1; x1 = -y1; y1 = x;}x = x0; y = y0; d = (x1 - x0) - 2 * (y1 - y0);while (x < x1 + 1){if (flag == 1) g.DrawRectangle(Pens.Red, x, y, 1, 1);if (flag == 2) g.DrawRectangle(Pens.Red, x, -y, 1, 1);if (flag == 3) g.DrawRectangle(Pens.Red, y, x, 1, 1);if (flag == 3) g.DrawRectangle(Pens.Red, y, -x, 1, 1);x++;if (d > 0){d = d - 2 * (y1 - y0);}else{y++;d = d - 2 * ((y1 - y0) - (x1 - x0));}}}
(5)运行结果
3.生成圆的Bresenham算法
(1)在“基本图形生成”菜单项下选中子菜单“Bresenham圆”,将子菜单的Name属性值改为“BresenhamCircle”
(2)双击子菜单项“Bresenham圆”,在系统生成的菜单响应函数BresenhamCircle_Click中增添如下内容
private void BresenhamCircle_Click(object sender, EventArgs e){MenuID = 5; PressNum = 0;Graphics g = CreateGraphics(); //创建图形设备g.Clear(BackColor1); //设置背景色}
(3)和直线生成一样,这里的响应函数只是做一个基本图形生成的类型标识,真正的图形生成操作在鼠标操作中完成。鼠标画圆的操作方式确定为:先用鼠标确定圆心,再用鼠标确定圆上任意一点。在鼠标点击响应函数中插人如下语句
private void Form1_MouseClick(object sender, MouseEventArgs e){Graphics g = CreateGraphics(); //创建图形设备Pen MyPen = new Pen(Color.Red, 1);if (MenuID == 1 || MenuID == 2){if (PressNum == 0) //第一点,保留{FirstX = e.X;FirstY = e.Y;OldX = e.X;OldY = e.Y;}else //第二点,画线{if (MenuID == 1)DDALine1(FirstX, FirstY, e.X, e.Y);if (MenuID == 2)MidLine1(FirstX, FirstY, e.X, e.Y);}PressNum++;if (PressNum >= 2){PressNum = 0; //画线完毕,清零,为画下一条线做准备}}if (MenuID == 5) //画圆部分{if (PressNum == 0) //圆心,保留{FirstX = e.X;FirstY = e.Y;}else //圆上任意一点,确定半径{if (FirstX == e.X && FirstY == e.Y) return;BresenhamCircle1(FirstX, FirstY, e.X, e.Y);}PressNum++;if (PressNum >= 2){PressNum = 0; //画圆完毕,清零,为画下一个圆做准备}}}
(4)在鼠标移动响应函数中插入如下语句
private void Form1_MouseMove(object sender, MouseEventArgs e){Graphics g = CreateGraphics(); //创建图形设备Pen BackPen = new Pen(BackColor1, 1);Pen MyPen = new Pen(ForeColor1, 1);if ((MenuID == 1 || MenuID == 2) && PressNum == 1){if (!(e.X == OldX && e.Y == OldY)){g.DrawLine(BackPen, FirstX, FirstY, OldX, OldY);g.DrawLine(MyPen, FirstX, FirstY, e.X, e.Y);OldX = e.X;OldY = e.Y;}}if (MenuID == 5 && PressNum == 1){if (!(e.X == OldX && e.Y == OldY)){//求圆半径double r = Math.Sqrt((FirstX - OldX) * (FirstX - OldX) + (FirstY - OldY) * (FirstY - OldY));int r1 = (int)(r + 0.5); //取整g.DrawEllipse(BackPen, FirstX - r1, FirstY - r1, 2 * r1, 2 * r1);//擦除旧圆//求圆半径r = Math.Sqrt((FirstX - e.X) * (FirstX - e.X) + (FirstY - e.Y) * (FirstY - e.Y));r1 = (int)(r + 0.5); //取整g.DrawEllipse(MyPen, FirstX - r1, FirstY - r1, 2 * r1, 2 * r1);}}}
(5)g.DrawEllipse函数是系统提供的画椭圆函数,这里借助它,通过画一个长短轴相等的椭圆,实现画圆的橡皮筋。BresenhamCircle1函数是真正用圆的算法实现画圆的函数,还没建立。在程序Form1.cs程序中建立BresenhamCircle1函数如下
private void BresenhamCircle1(int x0, int y0, int x1, int y1){int r, d, x, y;Graphics g = CreateGraphics(); //创建图形设备r = (int)(Math.Sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0)) + 0.5);x = 0; y = r; d = 3 - 2 * r;while (x < y || x == y){g.DrawRectangle(Pens.Blue, x + x0, y + y0, 1, 1);g.DrawRectangle(Pens.Red, -x + x0, y + y0, 1, 1);g.DrawRectangle(Pens.Green, x + x0, -y + y0, 1, 1);g.DrawRectangle(Pens.Yellow, -x + x0, -y + y0, 1, 1);g.DrawRectangle(Pens.Black, y + x0, x + y0, 1, 1);g.DrawRectangle(Pens.Red, -y + x0, x + y0, 1, 1);g.DrawRectangle(Pens.Red, y + x0, -x + y0, 1, 1);g.DrawRectangle(Pens.Red, -y + x0, -x + y0, 1, 1);x++;if (d < 0 || d == 0){d = d + 4 * x + 6;}else{y = y - 1;d = d + 4 * (x - y) + 10;}}}
(6)运行结果
计算机图形学实习教程之基本图形的生成(直线DDA算法,直线中点算法,Bresenham画圆算法),利用C#实现,附源码相关推荐
- 【计算机图形学】小白谈计算机图形学(二)画圆篇之中点画圆法,Bresenham画圆算法,椭圆实操,线型处理详解
小白谈计算机图形学(二)画圆篇之中点画圆法,Bresenham画圆算法,椭圆实操,线型处理详解 引言 如何画圆 基本思想 中点画圆法 中点画圆基本思路 中点画圆改进 Bresenham画圆算法 Bre ...
- 中点Bresenham画圆算法|MFC|计算机图形学
中点Bresenham画圆算法|MFC|计算机图形学 Bresenham中点画圆算法 计算机图形学-基本图元的生成-圆 基于学习直线的生成算法后,又展开了圆.椭圆的讲解: 此次试验是简单的MFC应用, ...
- 【计算机图形学】中点画圆算法和Bresenham画圆算法
在平面解析几何中,圆的方程可以描述为(x – x0)2 + (y – y0)2 = R2,其中(x0, y0)是圆心坐标,R是圆的半径,特别的,当(x0, y0)就是坐标中心点时,圆方程可以简化为x2 ...
- 计算机图形学(1)基本图形算法
计算机图形学--基本图形算法 光栅图形中点的表示 屏幕坐标系在左上角 地址=(Xmax-Xmin)[每行像素点数]*(Y-Ymin)[行数]+(X-Xmin)[行中位置]+基地址 直线扫描转换算法 假 ...
- 计算机图形学孔令德基础知识,计算机图形学基础教程孔令德答案
计算机图形学基础教程孔令德答案 [篇一:大学计算机图形学课程设] 息科学与工程学院课程设计任务书 题目: 小组成员:巴春华.焦国栋 成员学号:专业班级:计算机科学与技术.2009级本2班课程: 计算机 ...
- 计算机图形学结课论文,计算机图形学基础教程结课论文
计算机图形学是研究如何在计算机中生成.显示和处理图形的一门学科.计算机图形学具有较高的实用价值.下面是学习啦小编给大家推荐的计算机图形学基础教程结课论文,希望大家喜欢! 计算机图形学基础教程结课论文篇 ...
- 计算机图形学基础教程代码,计算机图形学基础教程
<计算机图形学基础教程>由会员分享,可在线阅读,更多相关<计算机图形学基础教程(19页珍藏版)>请在人人文库网上搜索. 1.第一章 1. 计算机图形学的主要研究内容是什么? 答 ...
- 计算机图形学二维图形基本变换实验原理,计算机图形学实验:二维图形变换.docx...
计算机图形学实验:二维图形变换.docx (9页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 19.90 积分 实验三 二维图形变换一.实验任务1. 通 ...
- 计算机图形学 实验7 《复杂图形绘制-Bezier曲线与Hermite曲线》
计算机图形学 实验7 <复杂图形绘制-Bezier曲线与Hermite曲线> 一.实验目的 学习样条曲线的绘制. 二.实验内容 1.绘制Bezier曲线: 2.绘制Hermite曲线. 三 ...
最新文章
- 送餐送货机器人、自动驾驶车、扫地机器人,再也不用担心撞上玻璃橱窗了丨CVPR2020...
- python 判断变量是否是 None 的三种写法
- 手机卫士09_应用程序四种查看_ListView小标题_进程管理
- 计算机网络(二十三)-网络层-概述与数据交换方式
- break和continue的方法(break 直接跳出循环)与 (continue本次忽略,但之后的继续)
- Windows8中离线安装.Net 3.5的方法
- 安卓Notification通知栏全解
- 用OFFICE 2007发送的文章
- 在 Silverlight 中管理动态内容交付,第 1 部分
- Mybatis多表新增
- visio的替代工具 - draw.io
- java 控制台 全屏_Java全屏模式与退出全屏:
- 在JS数组特定索引处指定位置插入或修改元素的技巧
- 【论文阅读】Phase-aware speech enhancement with deep complex U-net
- C语言中求余运算符的注意事项
- Python Web 框架-Django day05
- 苹果故意降低旧手机性能 曾经创新巨擘为何沦落风尘?
- 海报创意|十月的节日热点:国庆、重阳和万圣节
- 哈啰出行Java面试
- 用python进行图片素描
热门文章
- AVAGO MegaRAID SAS 9361-8i配置IPMI以及JBOD直通模式
- Sandstorm 建设者亮点——2023 年 2 月
- 关于WiderPerson数据说明(使用后笔记)
- 郑州高新区php平均收入,郑州公布各区平均工资,你又拖后腿了?
- Python基础——格式化输出
- char * name字符串使用
- MySQL在线升级方案
- 计算机原理学习指导第3版,计算机组成原理学习指导与习题解析(第3版)(21世纪大学本科计算机...
- 在RHEL5下安装腾迅QQ(VMware中进行)
- 【汇正财经】国家股是什么意思?什么是国家股?