计算机图形学实验—中点算法画直线
VS中直线的绘制—计算机图形学实验报告一
Else
k += 2 * (dy - dx)
y = y + 1
Enห้องสมุดไป่ตู้If
x = x + 1
EndWhile
Else
k = 2 * dx - dy
Whiley < y2
g.DrawEllipse(p,CInt(x),CInt(y), 1, 1)
Ifk < 0Then
k += 2 * dx
08地信
学号
200875000203
姓名
指导老师
课程名称
计算机图形学
实验题目
直线的绘制
成绩
一、实验目的:
熟练掌握绘制直线的DDA算法、中点画线算法和Bresenham画线算法。
二、实验准备:
学习绘制直线的DDA算法、中点画线算法和Bresenham画线算法,注意考虑不同斜率条件下算法的变化。
三、实验内容:
MessageBox.Show("请输入正确的坐标!", "警告!", MessageBoxButtons.OK, MessageBoxIcon.Warning)
Else
x1 =CDbl(TextBox1.Text)
y1 =CDbl(TextBox2.Text)
x2 =CDbl(TextBox3.Text)
Dimx1, y1, x2, y2, dx, dy, x, y, k, a, bAsDouble
DimgAsGraphics = PictureBox1.CreateGraphics
DimpAsPen =NewPen(Color.Green, 1)
计算机图形学--绘制直线
计算机图形学实验报告专业:信息与计算科学班级: 1002班学号: 10080602** 姓名: *****1.实验目的熟悉CDC类的MoveTo()和LineTo()直线段绘制函数。
熟悉斜率-1<k<0内任意值的直线段的中点Bresenham扫描转换算法。
2.问题分析通过Cline类来模拟CDC类完成任意斜率的直线段绘制,同样提供MoveTo()和LineTo()成员函数。
3.实验步骤(1)规定颜色的处理,定义了CRGB类.(2)设计CLine直线类.(3)在直线类中创建MoveTo()和LineTo()成员函数.4.部分程序代码#Line.hclass CLine{public:CLine();virtual ~CLine();void MoveTo(double,double);void LineTo(CDC* pDC,double,double,double);public:CPoint m_p1;CPoint m_p2;};#Line.cppCLine::CLine(){}CLine::~CLine(){}void CLine::MoveTo(double x,double y){m_p1=CPoint(x,y);}void CLine::LineTo(CDC* pDC,double x,double y,double k) {m_p2=CPoint(x,y);CPoint p,t;pDC->SetMapMode(MM_LOMETRIC);pDC->SetViewportOrg(200,200);double d;if(k>=-1.0&&k<0.0){if(m_p1.x >m_p2.x ){t=m_p1;m_p1=m_p2;m_p2=t;}d=-0.5-k;for(p=m_p1;p.x <m_p2.x ;p.x ++){pDC->SetPixel (p.x ,p.y ,RGB(0,0,255));if(d>0){p.y--;d-=1+k;}else{d-=k;}}}}void CTEXTView::OnDraw(CDC* pDC){CTEXTDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);CLine cline;cline.MoveTo (-200,300);cline.LineTo (pDC,200,-300,-0.3);}5.程序效果图6.实验总结本实验实现了一个类似于CDC类的MoveTo()函数和LineTo()函数,用于绘制任意斜率的直线段,这次只是绘制固定斜率的直线段,但还是出现了很多问题,经过与同学的讨论解决了问题。
华中科技大学计算机图形学实验报告——画直线、日地月模型
计算机图形学基础实验报告专业:班级:姓名:学号:日期:OpenGL简介(1)OpenGL作为一个性能优越的图形应用程序设计界面(API),它独立于硬件和窗口系统,在运行各种操作系统的各种计算机上都可用,并能在网络环境下以客户/服务器模式工作,是专业图形处理、科学计算等高端应用领域的标准图形库。
它具有以下功能。
1. 模型绘制2. 模型观察在建立了三维景物模型后,就需要用OpenGL描述如何观察所建立的三维模型。
3. 颜色模式的指定OpenGL应用了一些专门的函数来指定三维模型的颜色。
4. 光照应用用OpenGL绘制的三维模型必须加上光照才能更加与客观物体相似。
5. 图象效果增强OpenGL提供了一系列的增强三维景观的图象效果的函数,这些函数通过反走样、混合和雾化来增强图象的效果。
6. 位图和图象处理OpenGL还提供了专门对位图和图象进行操作的函数。
7. 纹理映射8. 实时动画9. 交互技术应用软件OpenGL窗口系统操作系统图形硬件图1.1 OpenGL图形处理系统的层次结构(2)OpenGL的操作步骤在OpenGL中进行的图形操作直至在计算机屏幕上渲染绘制出三维图形景观的基本步骤如下:1. 根据基本图形单元建立景物模型,得到景物模型的数学描述(OpenGL 中把点、线、多边形、图像和位图都作为基本图形单元);2. 把景物模型放在三维空间中的合适的位置,并且设置视点(Viewpoint)以观察所感兴趣的景观;3. 计算模型中所有物体的色彩,同时确定光照条件、纹理粘贴方式等;4. 把景物模型的数学描述及其色彩信息转换至计算机屏幕上的像素,这个过程也就是光栅化(rasterization)。
在这些步骤的执行过程中,OpenGL可能执行其他的一些操作,例如自动消隐处理等。
另外,景物光栅化之后被送入帧缓冲器之前还可以根据需要对象素数据进行操作。
(3)OpenGL的组成OpenGL不是一种编程语言,而是一种API(应用程序编程接口),它实际上是一种图形与硬件的接口,包括了多个图形函数。
计算机图像图形学-中点画线法
场景渲染
通过中点画线法,游戏开 发者可以快速渲染复杂的 场景,提高游戏运行效率。
计算机辅助设计
机械零件绘图
在计算机辅助设计中,中 点画线法可以用于绘制机 械零件的轮廓和细节,提 高绘图精度。
建筑设计
中点画线法可以用于建筑 设计领域,生成建筑物的 平滑轮廓,提高设计效果。
电路板设计
在电路板设计中,中点画 线法可以用于绘制电路路 径,优化电路布局和信号 传输。
图像处理与编辑
图像平滑处理
中点画线法可以用于图像平滑处 理,减少图像中的噪声和细节失
真。
图像修复
中点画线法可以用于图像修复,对 损坏或缺失的图像部分进行修复和 填充。
图像变换与合成
通过中点画线法,图像处理与编辑 软件可以实现图像的缩放、旋转和 平移等变换操作,以及图像合成和 拼接等操作。
PART 04
优化线条质量可以提高绘制的准确性和视觉效果,使线条 更加平滑、自然。
PART 03
中点画线法的应用场景
REPORTING
WENKU DESIGN
游戏开发
01
02
03
游戏中的பைடு நூலகம்图绘制
中点画线法可以用于游戏 中的地图绘制,生成平滑、 连续的路径,提高游戏体 验。
角色移动动画
在游戏开发中,中点画线 法可以用于生成角色移动 动画,使角色移动更加自 然流畅。
PART 02
中点画线法的实现过程
REPORTING
WENKU DESIGN
确定起点和终点
01
确定线条的起点和终点是中点画 线法的第一步,通常通过输入坐 标或鼠标点击屏幕上的位置来确 定。
02
起点和终点的坐标需要精确,否 则可能导致线条绘制错误或出现 偏差。
《计算机图形学》实验指导书
计算机图形学实验指导书袁科计算机技术实验中心目录实验一实现DDA、中点画线算法和Bresenham画线算法 (24)实验二实现Bezier曲线 (25)实验三实现B样条曲线 (26)实验四实现多边形填充的边界标志算法 (27)实验五实现裁剪多边形的Cohen-Sutherland算法 (28)实验六二维图形的基本几何变换 (30)实验七画图软件的编制 (31)实验一实现DDA、中点画线算法和Bresenham画线算法【实验目的】1、掌握直线的多种生成算法;2、掌握二维图形显示原理。
【实验环境】VC++6.0/ BC【实验性质及学时】验证性实验,2学时,必做实验【实验内容】利用任意的一个实验环境,编制源程序,分别实现直线的三种生成算法,即数字微分法(DDA)、中点画线法以及Bresenham画线算法。
【实验原理】1、数字微分法(Digital Differential Analyzer,DDA)算法思想:基于直线的微分方程来生成直线。
ε=1/max(|△x|,|△y|)max(|△x|,|△y|)=|△x|,即|k|≤1 的情况:max(|△x|,|△y|)=|△y|,此时|k|≥1:2、中点画线法算法思想:每次在最大位移方向上走一步,另一方向是否走步取决于误差项的判断。
3、Bresenham画线算法算法思想:其基本思想同中点算法一样,即每次在最大位移方向上走一步,而另一个方向是否走步取决于误差项的判断。
【实验要求】1.上交源程序;2.上交实验报告,实验报告内容如下:(1) 实验名称(2) 实验目的(3) 算法实现的设计方法及程序流程图(4) 程序结果分析【分析与思考】(1) 上述所阐述的三个算法,其基本算法只能适用于直线的斜率(|K|<=1) 的情形,如何将上述算法进行推广,使其能够处理任意斜率的直线?(2) 计算机显示屏幕的坐标圆心在哪里,与我们平时的习惯有什么差异,如何协调二者?实验二 实现Bezier 曲线【实验目的】1、掌握Bezier 曲线的定义;2、能编程实现N 次Bezier 曲线的绘制与显示。
计算机图形学实验一画直线
贵州大学实验报告
学院:计算机科学与技术专业:计算机科学与技术班级:计科131
算法原理:
与DDA算
法相似,
Bresenham
画线算法也
要在每列象
素中找到与
理想直线最逼近的象素点。
根据直线的斜率来确定变量在x或y方向递增一个单位。
另一个方向y或x的增量为0或1,它取决于实际直线与最接近网格点位置的距离。
这一距离称为误差。
算法的巧妙构思,使每次只需检查误差项(增量)的符号即可。
定义决策变量:d =d+k (0<k<1)设0<k<1,如直线上的一点为(x,y),则下一点为:(x+1,y) (d< 或(x+1,y+1)(d>=当d>1时,让d=d-1,以保证0<=d<1,d0=0
令e = (0<k<1),则e0 =
则下一点为:
(x+1,y),(e<0)
(x+1,y+1)(e>=0)
当e >0时, 让e =e-1,(重新初始化误差项)由于算法只用到误差项的符号,为了改用整数以避免除法,可以作如下替换:
e = 2*e*dx定义决策变量e= 2*e*dx,则e0 = -dx,e=e +2*dy
printf("输入有误,请重新输入\n");
break;
}
}
return 0;
}
实
验
结
果
实
验总结
通过这次试验我对于中点生成算法和Bresenham生成算法有了进一步的了解,在平时上课的基础上对计算机图形学有了更深的认识,同时对课程内容也更加了解。
计算机图形学实验一:画直线
贵州大学实验报告学院:计算机科学与技术专业:计算机科学与技术班级:计科131如果 d<0,则M在理想直线下方,选右上方P1点;如果 d=0,则M在理想直线上,选P1/ P2点。
由于d是xi和yi的线性函数,可采用增量计算提高运算效率。
1.如由pi点确定在是正右方P2点(d>0).,则新的中点M仅在x方向加1,新的d值为:d new=F(xi+2,yi+0.5)=a(xi+2)+b(yi+0.5)+c而 d old=F(xi+1,yi+0.5)=a(xi+1)+b(yi+0.5)+cd new=d old+a= d old-dy2.如由pi点确定是右上方P1点(d<0),则新的中点M在x和y方向都增加1,新的d值为d new=F(xi+2,yi+1.5)=a(xi+2)+b(yi+1.5)+c而 d old=F(xi+1,yi+0.5)=a(xi+1)+b(yi+0.5)+cd new=d old+a+b= d old-dy+dx在每一步中,根据前一次第二迭中计算出的d值的符号,在正右方和右上方的两个点中进行选择。
d的初始值: d0=F(x0+1,y0+0.5)=F(x0,y0)+a+b/2=a+b/2=-dy+dx/2 F(x0,y0)=0,(x0,y0)在直线上。
为了消除d的分数,重新定义 F(x,y)=2(ax+by+c)则每一步需要计算的d new 是简单的整数加法dy=y1-y0,dx=x1-x0d0=-2dy+dxd new=d old-2*dy,当 d old>=0d new=d old-2(dy-dx),当d old<0Bresenham画线算法算法原理:与DDA算法相似,Bresenham画线算法也要在每列象素中找到与理想直线最逼近的象素点。
根据直线的斜率来确定变量在x或y方向递增一个单位。
另一个方向y或x实验内容#include"stdafx.h"#include<glut.h>#include<iostream>#include<cmath>#include<stdio.h>using namespace std;void init(){glClearColor(1.0, 1.0, 1.0, 1.0);glMatrixMode(GL_PROJECTION);glLoadIdentity();gluOrtho2D(0.0, 200.0, 0.0, 150.0);}void IntegerBresenhamline(){int x1 = 10, y1 = 10, x2 = 150, y2 = 100;int dx = abs(x2 - x1);int dy = abs(y2 - y1);int x, y;int e = -dx;if (x1 > x2){x = x2;y = y2;x2 = x1;}else{x = x1;y = y1;}glClear(GL_COLOR_BUFFER_BIT);glColor3f(1.0, 0.0, 0.0);glBegin(GL_LINES);glVertex2i(x, y);while (x < x2){if (e >= 0){y++;e = e - 2 * dx;}glVertex2i(x, y);x++; e += 2 * dy;}glEnd();glFlush();}void MidPointLine(){int x, y, x1 = 10, y1 = 10, x2 = 150, y2 = 100;int dy = y1 - y2;int dx = x2 - x1;int d = 2 * dy + dx;int dx1 = 2 * dy;int dx2 = 2 * (dx + dy);if (x1 > x2){x = x2;y = y2;x2 = x1;}else{x = x1;y = y1;}glClear(GL_COLOR_BUFFER_BIT);glColor3f(1.0, 0.0, 0.0);glBegin(GL_LINES);glVertex2i(x, y);while (x < x2){if (d<0){y++; x++;d += dx2;}else{x++, d += dx1;}glVertex2i(x, y);}glEnd();glFlush();}int main(int argc, char** argv){glutInit(&argc, argv);glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);glutInitWindowPosition(50, 100);glutInitWindowSize(400, 300);int choice;printf("输入你想画的直线 0代表Bresenham 1代表中点画线\n");while (1){scanf("%d", &choice);switch (choice){case 0:glutCreateWindow("Bresenham Draw Line");init();glutDisplayFunc(IntegerBresenhamline);glutMainLoop();break;case 1:glutCreateWindow("middle Point Line");init();glutDisplayFunc(MidPointLine);glFlush();glutMainLoop();break;default:printf("输入有误,请重新输入\n");break;}}return 0;}实验结果实验总结通过这次试验我对于中点生成算法和Bresenham生成算法有了进一步的了解,在平时上课的基础上对计算机图形学有了更深的认识,同时对课程内容也更加了解。
计算机图形学作业(中点法画直线和八分画圆法)
}
x=x0;y=y0;
dx=x1-x0;dy=y1-y0;
d=dx-2*dy;
up=2*x-2*y;
down=-2*dy;
while(x<=x1){
pDC->SetPixel(x,y,color);
x++;
if(d<0){
y++;
d+=up;
}
else d+=down;
}
}
void CMy213View::OnButton32772()
{
CDC *pDC;
pDC=this->GetDC();
int x0=50,y0=50,x1=300,y1=300,color=333;
MidBresenhamLine(pDC,x0,y0,x1,y1,color);
this->ReleaseDC(pDC);
计算机图形学作业中点法画直线和八分画圆法计算机图
1、中点法画直线:
void MidBresenhamLine(CDC *pDC,int x0,int y0,int x1,int y1,int color){
int dx,dy,){
x=x1;x1=x0;x0=x;
}
x++;
}
}
void CmbView::Onbbb()
{
CDC *pDC;
pDC=this->GetDC();
int r=60,color=333;
MidBresenhamCircle(pDC,r,color);
this->ReleaseDC(pDC);
计算机图形学 (中点画线)
西北师范大学计算机科学与工程学院学生实验报告学号专业计算机科学与技术班级师范一班姓名课程名称计算机图形学课程类型专业限选实验名称实验一中点画直线一、实验目的:1.了解画直线的基本思想;2.掌握画直线的基本步骤。
二、实验原理假定直线斜率k在0~1之间,当前象素点为(x p,y p),则下一个象素点有两种可选择点P1(x p+1,y p)或P2(x p+1,y p+1)。
若P1与P2的中点(x p+1,y p+0.5)称为M,Q为理想直线与x=x p+1垂线的交点。
当M在Q的下方时,则取P2应为下一个象素点;当M在Q的上方时,则取P1为下一个象素点。
这就是中点画线法的基本原理。
下面讨论中点画线法的实现。
过点(x0,y0)、(x1, y1)的直线段L的方程式为F(x,y)=ax+by+c=0,其中,a=y-y1, b=x1-x0, c=x0y1-x1y0,欲判断中点M在Q点的上方还是下方,只要把M代入F(x,y),并判断它的符号即可。
为此,我们构造判别式:d=F(M)=F(x+1, y p+0.5)=a(x p+1)+b(y p+0.5)+cp当d<0时,M在L(Q点)下方,取P2为下一个象素;当d>0时,M在L(Q点)上方,取P1为下一个象素;当d=0时,选P1或P2均可,约定取P1为下一个象素;注意到d是x p, y p的线性函数,可采用增量计算,提高运算效率。
initgraph(&gdriver,&gmode,"");for (i=0;i<100;i++){DDAline(1,1,450,300,4);}getch();closegraph();}四、实例举例:用中点画线方法扫描转换连接两点P0(0,0)和P1(5,2)的直线段。
a=y0-y1=-2; b=x1-x0=5; d0=2*a+b=1;d1=2*a=-4;d2=2*(a+b)=6 ,x y d0 0 11 0 -32 1 33 1 -14 2 55 2 15五、实验截图:。
实验1中点画线和Bresenham画线算法的实现
实验1中点画线和Bresenham画线算法的实现计算机图形学实验报告实验1 使用画线算法,绘制直线段一.实验目的及要求(1)掌握图形学中常用的三种画线算法:数值微分法、中点画线法和Bresenham画线算法。
(2)掌握绘制直线的程序设计方法。
(3)掌握使用文件来保存直线段的方法。
(4)掌握从文本文件中恢复出直线的方法。
二.实验内容使用VC++ 6.0开发环境,分别实现中点画线算法和Bresenham 画线算法,绘制直线(注意,不能使用VC中已有的绘制直线的函数),并以文本文件的形式保存绘制的结果,可以从文本文件中恢复出以前绘制过的直线。
三.算法设计与分析Bresenham算法绘制直线的程序(仅包含整数运算)。
void MidBresenhamLine(int x0,int y0,int x1,int y1,int color) {int dx,dy,d,UpIncre,DownIncre,x,y;if(x0>x1){x=x1;x1=x0;x0=x;y=y1;y1=y0;y0=y;}x=x0;y=y0;dx=x1-x0;dy=y1-y0;d=dx-2*dy;UpIncre=2*dx-2*dy;DownIncre=-2*dy;while(x<=x1){putpixel(x,y,color);X++;if(d<0){y++;d+=UpIncre;}else d+=DownIncre;}}四.程序调试及运行结果的自我分析与自我评价// testView.cpp : implementation of the CT estView class#include "stdafx.h"#include "test.h"#include "testDoc.h"#include "testView.h"#include // ifstream、ofstream等位于其中#include#include // string类型需要#include "DlgInput.h" //CDlgInput类的头文件using namespace std;#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif// CTestViewIMPLEMENT_DYNCREATE(CTestView, CView)BEGIN_MESSAGE_MAP(CTestView, CView)//{{AFX_MSG_MAP(CTestView)ON_COMMAND(ID_MENUITEM32771, OnMenuitem32771)ON_COMMAND(ID_MENUBRESENHAMLINE, OnMenubresenhamline) ON_COMMAND(ID_MENUCLEARVIEW, OnMenuclearview)ON_COMMAND(ID_FILE_OPEN, OnFileOpen)ON_COMMAND(ID_FILE_SA VE, OnFileSave)//}}AFX_MSG_MAP// Standard printing commandsON_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()// CTestView construction/destructionCTestView::CTestView(){// TODO: add construction code herem_nFlag = -1; // 不是任何绘图类型}CTestView::~CT estView(){}BOOL CTestView::PreCreateWindow(CREATESTRUCT& cs){// TODO: Modify the Window class or styles here by modifying// the CREATESTRUCT csreturn CView::PreCreateWindow(cs);}// CTestView drawingvoid CTestView::OnDraw(CDC* pDC){CTestDoc* pDoc = GetDocument();ASSERT_V ALID(pDoc);// TODO: add draw code for native data hereif(1==m_nFlag) // 中点画线{MidPointLine(m_X0, m_Y0, m_X1, m_Y1, RGB(255,0,0) );}else if(2==m_nFlag) // Bresenham画线{BresenhamLine(m_X0, m_Y0, m_X1, m_Y1, RGB(0,255,0) );}}// CTestView printingBOOL CTestView::OnPreparePrinting(CPrintInfo* pInfo){// default preparationreturn DoPreparePrinting(pInfo);}void CTestView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/){// TODO: add extra initialization before printing}void CTestView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/){// TODO: add cleanup after printing}// CTestView diagnostics#ifdef _DEBUGvoid CTestView::AssertValid() const{CView::AssertValid();}void CTestView::Dump(CDumpContext& dc) const{CView::Dump(dc);}CTestDoc* CTestView::GetDocument() // non-debug version is inline{ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CT estD oc)));return (CT estDoc*)m_pDocument;}#endif //_DEBUG// CTestView message handlersvoid CTestView::OnMenuitem32771(){// TODO: Add your command handler code herem_nFlag = 1; // 中点画线CDlgInput dlg;if(IDOK==dlg.DoModal()){m_X0=dlg.m_nX0;m_Y0=dlg.m_nY0;m_X1=dlg.m_nX1;m_Y1=dlg.m_nY1;RedrawWindow(); //重绘窗口}}void CTestView::OnMenubresenhamline(){// TODO: Add your command handler code herem_nFlag = 2; // Bresenham画线CDlgInput dlg;if(IDOK==dlg.DoModal()){m_X0=dlg.m_nX0;m_Y0=dlg.m_nY0;m_X1=dlg.m_nX1;m_Y1=dlg.m_nY1;RedrawWindow(); //重绘窗口}}// 算法: 中点画线// 输入: 起点(x0,y0),终点(x1,y1);// 输入要求x0<=x1;void CTestView::MidPointLine( int x0, int y0, int x1, int y1, int color ){CDC * pDC=GetDC();int a,b,d0,d1,d2,d3,d4,d5,d,x,y;a=y0-y1;b=x1-x0; // 之前的设置已经保证始终有x1>=x0d=2*a+b;d0=2*a-b;d1=2*a;d2=2*(a+b);d3=2*b;d4=2*(a-b);d5=a-2*b;x=x0;y=y0;pDC->SetPixel(x,y,color);if(x==x1) // 斜率k为无穷大{if(y<=y1){while(y<=y1){pDC->SetPixel(x,y,color);y++;}}else{while(y>=y1){pDC->SetPixel(x,y,color);y--;}}}// if 斜率k为无穷大else // 斜率k为有限值{// double k=-a/b;// if( k+1>1e-6 && k-1<1e-6 || fabs(k-1)<1e-6 || fabs(k+1)<1e-6) // |k|<=1(即:-1<= k <=1),与1e-6比较是浮点数比较方法if( -b<=-a && -a<=b ) // 用浮点数比较在|k|=1.0f时容易出问题,所以直接用整数比较(将斜率k转换为a与b的比较;之前的设置已经保证b为正数){if(y<=y1){while(x<x1)< p="">{if(d<0){x++;y++;d+=d2;}else{x++;d+=d1;}pDC->SetPixel(x,y,color);}}else{while(x<x1)< p="">{if(d0<0){ x++;d0+=d1;}else{ x++;y--; d0+=d4; }pDC->SetPixel(x,y,color);}}}// if( |k|<=1 )else // |k|>1{if(y<=y1){while(x<x1)< p="">{if(d<0){y++;d+=d3;}else{y++;x++;d+=d2;}pDC->SetPixel(x,y,color);}}else{while(x<x1)< p="">{if(d5<0){ x++;y--; d5+=d4;}else{y--; d5+=-2*b;}pDC->SetPixel(x,y,color);}}}// else( |k|>1 )}// else 斜率k为有限值ReleaseDC(pDC);}// 算法: Bresenham画线// 输入: 起点(x0,y0),终点(x1,y1);// 输入要求x0<=x1;void CTestView::BresenhamLine( int x0, int y0, int x1, int y1, int color ){ CDC * pDC=GetDC();int x,y,dx,dy,e;dx=x1-x0;dy=y1-y0;e=-dx;x=x0;y=y0;while(x<=x1){ pDC->SetPixel(x,y,color);x++;e=e+2*dy;if(e>0){y++;e=e-2*dx;}}}void CTestView::OnMenuclearview(){// TODO: Add your command handler code here m_X0=0;m_Y0=0;m_X1=0;m_Y1=0;RedrawWindow();//重绘窗口}// 打开过去保存的文件,该文件包含直线的端点坐标void CTestView::OnFileOpen(){// TODO: 在此添加命令处理程序代码if( m_nFlag!=1 && m_nFlag!=2 ){MessageBox("请先在菜单中选择绘制直线的方法!","提示",MB_ICONWARNING);return;}CFileDialog dlgFile (TRUE, _T("txt"), _T(""),OFN_FILEMUSTEXIST| OFN_HIDEREADONL Y, _T("线段端点坐标文件(*.txt)|*.txt||"), this);if( IDOK == dlgFile.DoModal()){CString fileName = dlgFile.GetFileName();ifstream rFile;rFile.open(fileName,ios::in);if ( ! rFile.is_open() ){MessageBox("文件打开失败!","提示",MB_ICONW ARNING);return;}CString strLine0;string strLine;int nX,nY;// 起点、终点,两个坐标rFile>>strLine;strLine0 = strLine.c_str();nX = atoi( strLine0.Left( strLine0.Find(",") ) ); // 解析文件,如“220,221”表示一个点的x、y坐标nY = atoi( strLine0.Mid( strLine0.Find(",")+1 ) );m_X0 = nX;m_Y0 = nY;rFile>>strLine;strLine0 = strLine.c_str();nX = atoi( strLine0.Left( strLine0.Find(",") ) );nY = atoi( strLine0.Mid( strLine0.Find(",")+1 ) );m_X1 = nX;m_Y1 = nY;RedrawWindow();rFile.close();}}// 保存当前视图上绘制的所有直线的端点坐标void CTestView::OnFileSave(){// TODO: 在此添加命令处理程序代码CFileDialog dlgFile(FALSE, _T("txt"), _T(""), OFN_OVERWRITEPROMPT, _T("线段端点坐标文件(*.txt)|*.txt||"), this);if( IDOK == dlgFile.DoModal()) // 保存文件{CString strFileName = dlgFile.GetFileName(); // 包含完整路径的文件名称ofstream wFile;wFile.open(strFileName,ios::out|ios::ate|ios::app);if ( ! wFile.is_open() ){MessageBox(strFileName+"文件创建失败!","提示",MB_ICONW ARNING);return;}wFile<<m_x0<<","<<m_y0<<="">wFile<<m_x1<<","<<m_y1<<="">五.实验心得及建议实验心得:Bresenham算法是一种很方便很实用很简单的算法,它对任意斜率的直线段具有通用性。
中点画线算法
中点画线算法中点画线算法(Midpoint Line Drawing Algorithm)是通过在每列像素中确定与理想直线最靠近的像素来进⾏扫描转换的。
步骤实现斜率: 0<=k<=1直线端点:(x1,y1),(x2,y2)1) 初始化。
令 a=y1-y2, b=x2-x1, d=2*a+b, deta1=2*a, deta2=2*(a+b), x=x1, y=y1.2) ⽤颜⾊color画像素(x,y)。
3) 判断x是否⼩于x2。
如果x代码实现(基于VC 6.0) 斜率: 任意1#define ROUND(a) ((int)(a+0.5))2/* 中点直线⽣成算法 */3void CDrawDC::LineMP(int x1, int y1, int x2, int y2, COLORREF color)4 {5int a,b,x,y,d,da1,da2;67if(x1<x2 && y1<y2){8 a=y1-y2;9 b=x2-x1;10 x=x1,y=y1;11 d=2*a+b;12 da1=2*a;13 da2=2*(a+b);1415 SetPixel(ROUND(x),ROUND(y),color);16for(;x<x2;){17if(d<0){18 x++;19 y++;20 d+=da2;21 }else{22 x++;23 d+=da1;24 }25 SetPixel(ROUND(x),ROUND(y),color);26 }27 }else if(x1>x2 && y1>y2){28 a=y2-y1;29 b=x1-x2;30 x=x2,y=y2;31 d=2*a+b;32 da1=2*a;33 da2=2*(a+b);3435 SetPixel(ROUND(x),ROUND(y),color);36for(;x<x1;){37if(d<0){38 x++;39 y++;40 d+=da2;41 }else{42 x++;43 d+=da1;44 }45 SetPixel(ROUND(x),ROUND(y),color);46 }47 }else if(x1>x2 && y1<y2){48 a=-y2;49 b=x1-x2;50 x=0,y=0;51 d=2*a+b;52 da1=2*a;53 da2=2*(a+b);5455 SetPixel(ROUND(x1-x),ROUND(y+y1),color);56for(;x<b;){57if(d<0){58 x++;59 y++;60 d+=da2;61 }else{62 x++;63 d+=da1;64 }65 SetPixel(ROUND(x1-x),ROUND(y+y1),color);66 }67 }else if(x1<x2 && y1>y2){68 a=-y1;69 b=x2-x1;70 x=0,y=0;71 d=2*a+b;72 da1=2*a;73 da2=2*(a+b);7475 SetPixel(ROUND(x2-x),ROUND(y+y2),color);76for(;x<b;){77if(d<0){78 x++;79 y++;80 d=d+da2;81 }else{82 x++;83 d+=da1;84 }85 SetPixel(ROUND(x2-x),ROUND(y+y2),color);86 }87 }88 }参考来源: 《计算机图形学实⽤教程(第三版)· 苏⼩红编著》。
《计算机图形学》实验报告
《计算机图形学》实验报告一、实验目的计算机图形学是一门研究如何利用计算机生成、处理和显示图形的学科。
通过本次实验,旨在深入理解计算机图形学的基本原理和算法,掌握图形的生成、变换、渲染等技术,并能够运用所学知识解决实际问题,提高对图形学的应用能力和编程实践能力。
二、实验环境本次实验使用的编程语言为 Python,使用的图形库为 Pygame。
开发环境为 PyCharm。
三、实验内容1、直线的生成算法DDA 算法(Digital Differential Analyzer)Bresenham 算法DDA 算法是通过计算直线的斜率来确定每个像素点的位置。
它的基本思想是根据直线的斜率和起始点的坐标,逐步计算出直线上的每个像素点的坐标。
Bresenham 算法则是一种基于误差的直线生成算法。
它通过比较误差值来决定下一个像素点的位置,从而减少了计算量,提高了效率。
在实验中,我们分别实现了这两种算法,并比较了它们的性能和效果。
2、圆的生成算法中点画圆算法中点画圆算法的核心思想是通过判断中点的位置来确定圆上的像素点。
通过不断迭代计算中点的位置,逐步生成整个圆。
在实现过程中,需要注意边界条件的处理和误差的计算。
3、图形的变换平移变换旋转变换缩放变换平移变换是将图形在平面上沿着指定的方向移动一定的距离。
旋转变换是围绕一个中心点将图形旋转一定的角度。
缩放变换则是改变图形的大小。
通过矩阵运算来实现这些变换,可以方便地对图形进行各种操作。
4、图形的填充种子填充算法扫描线填充算法种子填充算法是从指定的种子点开始,将相邻的具有相同颜色或属性的像素点填充为指定的颜色。
扫描线填充算法则是通过扫描图形的每一行,确定需要填充的区间,然后进行填充。
在实验中,我们对不同形状的图形进行了填充,并比较了两种算法的适用情况。
四、实验步骤1、直线生成算法的实现定义直线的起点和终点坐标。
根据所选的算法(DDA 或Bresenham)计算直线上的像素点坐标。
计算机图形学实验—中点算法画直线
计算机图形学实验报告班级:软件1102姓名:***学号:************中点算法的线段光栅化一、设计思想和算法流程1.假定直线斜率0<K<1假定直线斜率0<K<1,且已确定点亮象素点P (X p ,Y p ),则下一个与直线最接近的像素只能是P1点或P2点。
设M 为中点,Q 为交点,现需确定下一个点亮的象素。
当M 在Q 的下方-> P 2离直线更近更近->取P 2 。
M 在Q 的上方-> P 1离直线更近更近->取P 1M 与Q 重合, P 1、P 2任取一点。
问题:如何判断M 与Q 点的关系?由常识知:若y=kx+b;F(x,y)=y-kx-b;则有 ()()()⎪⎩⎪⎨⎧<>=点在直线下方0,点在直线上方0,点在直线上面0,y x F y x F y x F假设直线方程为:ax +by +c=0 (y=(-a/b)x-c/b)通过两点不能唯一确定a,b,c,取 a=y 0-y 1, b=x 1-x 0, c=x 0y 1-x 1y 0F(x,y)=ax +by +c=b(y-(-a/b)x-c/b); ()()()⎪⎩⎪⎨⎧<>=点在直线下方0,点在直线上方0,点在直线上面0,y x F y x F y x F则有∴欲判断M 点是在Q 点上方还是在Q 点下方,只需把M 代入F (x ,y ),并检查它的符号。
构造判别式:d=F(M)=F(x p +1,y p +0.5)=a(x p +1)+b(y p +0.5)+c当d<0,M 在直线(Q 点)下方,取右上方P 2;当d>0,M 在直线(Q 点)上方,取右方P 1;当d=0,选P 1或P 2均可,约定取P 1;能否采用增量算法呢?若d ≥0 ---->M 在直线上方->取P1;此时再下一个象素的判别式为 d 1=F(x p +2, y p +0.5)=a(x p +2)+b(y p +0.5)+c= a(x p +1)+b(y p +0.5)+c +a=d+a ;增量为a若d<0 ------>M 在直线下方->取P2;此时再下一个象素的判别式为 d 2= F(x p +2, y p +1.5)=a(x p +2)+b(y p +1.5)+c= a(x p +1)+b(y p +0.5)+c +a +b=d+a+b ;增量为a+b画线从(x0, y0)开始,d的初值d0=F(x0+1, y0+0.5)= a(x0 +1)+b(y0 +0.5)+c= F(x0, y0)+a+0.5b = a+0.5b由于只用d 的符号作判断,为了d来摆脱小数,提高效率。
贵州大学计算机图形学实验报告----直线生成算法
贵州大学计算机图形学实验报告学院:计算机科学与信息学院专业:软件工程班级:102班优点:用整数加法代替了DDA数值微分法中的浮点数加法及取整运算,大大提高了算法的效率。
缺点:在计算d的符号时,需要做4个加法和2个乘法改进:因为d是x和y的线性函数,因此可采用增量计算。
通过计算可得对于|k|<=1的情况d的初值为a+0.5b,当d>=0,M在L上方,增量d1为a;当d<0,M在L下方,增量d2为a+b。
对于|k|>1的情况d的初值为0.5a+b,当d>=0,M在L下方,增量d1为b;当d<0,M在L上方,增量d2为a+b。
三、Bresenham划线算法该算法是计算机图形学领域中使用最为广泛的直线扫描转换算法,该划线算法类似与中点划线算法,也是由误差项符号决定下一个像素右边点还是右上点。
基本原理:过各行各列像素中心构造一组虚拟网格线,按直线从起点到终点的顺序计算直线与各垂直网格线的交点,然后确定该列像素中与此交点最近的像素。
该算法的优点在于增量计算,使得对于每一列只要检查一个误差项的符号,就可以确定该列所求的像素。
根据直线的斜率来确定变量在x 或y方向递增一个单位。
另一个方向y或x的增量为0或1,它取决于实际直线与最接近网格点位置的距离。
这一距离称为误差。
由以上原理,为方便计算,令e = d-0.5,e的初值为-0.5,增量为k。
当 e>=0时,取当前像素(xi,yi)的右上方像素(xi+1,yi+1),e减小1,而当e<0时,更接近于右方像素(xi+1,yi)。
Bresenham算法的分析:优点:高效,巧妙地采用了e = d-0.5,e的初值为-0.5来简化运算,把e和0.5的比较转化成了e和0的比较,使得每次画点只需考虑误差项增量的符号即可。
斜率显示:中点划线算法斜率显示:Bresenham算法斜率显示:注:可根据教学需要对以上栏目进行增减。
表格内容可根据内容扩充。
计算机图形学 实验一直线生成算法报告
实验一直线生成算法一、实验目的及要求:1.学习C语言的基本绘图方法;2. 实习直线基本生成算法;3.了解光栅图形显示器的工作原理和特点;4.掌握课本所介绍的图形算法的原理和实现。
5. 基于光栅图形显示器,在c环境中使用基本图形生成算法画根粗细不同的直线。
1.)写出完整的DDA画线算法程序,使其可以画任意直线;2.)写出完整的中点画线算法程序,使其可以画任意直线;3.)写出完整的Breaenham画线程序,使其可以画任意直线;二、理论基础:1、DDA算法:实现的关键是如何步进和步进的方向:步进的正或负,决定能否正确的到达终点。
步进的大小:它控制了变化最大的步进,令其为单位步进,而另一个方向的步进必小于1 ,这样不论斜率|m|≤1否,都会使直线的亮度均匀。
依公式:则下一点坐标为:2、中点画法:假设x坐标为xp的各像素点中,与直线最近者已确定,为(xp,yp)。
那么,下一个与直线最近的像素只能是正右方的P1(xp+1,yp)或右上方的P2(xp+1,yp+1)两者之一。
再以M表示P1与P2的中点,即M=(xp+1,yp+0.5)。
又设Q是理想直线与垂直线x=xp+1的交点。
若M在Q的下方,则P2离直线近,应取为下一个像素;否则应取P1。
3、Bresenham算法:假设我们需要由 (x0, y0) 这一点,绘画一直线至右下角的另一点(x1, y1),x,y分别代表其水平及垂直座标。
在此我们使用电脑系统常用的座标系,即x座标值沿x轴向右增长,y座标值沿y轴向下增长。
因此x及y之值分别向右及向下增加,而两点之水平距离为x1 − x0且垂直距离为y1-y0。
由此得之,该线的斜率必定介乎于1至0之间。
而此算法之目的,就是找出在x0与x1之间,第x行相对应的第y列,从而得出一像素点,使得该像素点的位置最接近原本的线。
三、算法设计与分析:1、DDA算法:(1)已知过端点P0 (x0, y0), P1(x1, y1)的直线段L :y=kx+b(2)直线斜率为 :k=(y1-y0)/(x1-x0)(3)Xi+1=Xi+ε*ΔXYi+1=Yi+ε*ΔY 其中,ε=1/max(|ΔX|,|ΔY|)max(|ΔX|,|ΔY|)= |ΔX| (|k|<=1)|ΔY| (|k|>1)(4)|k|<=1时:Xi+1=Xi+(或-)1Yi+1=Yi+(或-)k|k|>1时:Xi+1=Xi+(或-)1/kYi+1=Yi+(或-)1这种方法直观,但效率太低,因为每一步需要一次浮点乘法和一次舍入运算。
计算机图形学--Bresenham完整算法-画直线、椭圆和圆
#include<windows.h>#include<gl/glut.h>#include"stdio.h"int m_PointNumber = 0; //动画时绘制点的数目int m_DrawMode = 1; //绘制模式 1 DDA算法画直线// 2 中点Bresenham算法画直线// 3 改进Bresenham算法画直线// 4 八分法绘制圆// 5 四分法绘制椭圆//绘制坐标线void DrawCordinateLine(void){int i = -250 ;//坐标线为黑色glColor3f(0.0f, 0.0f ,0.0f);glBegin(GL_LINES);for (i=-250;i<=250;i=i+10){glVertex2f((float)(i), -250.0f);glVertex2f((float)(i), 250.0f);glVertex2f(-250.0f, (float)(i));glVertex2f(250.0f, (float)(i));}glEnd();}//绘制一个点,这里用一个正方形表示一个点void putpixel(GLsizei x, GLsizei y){glRectf(10*x,10*y,10*x+10,10*y+10);}/////////////////////////////////////////////////////////////////////DDA画线算法 //// //// //// /////////////////////////////////////////////////////////////////////void DDACreateLine(GLsizei x0, GLsizei y0, GLsizei x1, GLsizei y1, GLsizei num) {//设置颜色glColor3f(1.0f,0.0f,0.0f);//对画线动画进行控制if(num == 1)printf("DDA画线算法:各点坐标\n");else if(num==0)return;//画线算法的实现GLsizei dx,dy,epsl,k;GLfloat x,y,xIncre,yIncre;dx = x1-x0;dy = y1-y0;x = x0;y = y0;if(abs(dx) > abs(dy)) epsl = abs(dx);else epsl = abs(dy);xIncre = (float)dx / epsl ;yIncre = (float)dy / epsl ;for(k = 0; k<=epsl; k++){putpixel((int)(x+0.5), (int)(y+0.5));if (k>=num-1) {printf("x=%f , y=%f,取整后 x=%d,y=%d\n", x, y, (int)(x+0.5),(int)(y+0.5));break;}x += xIncre;y += yIncre;if(x >= 25 || y >= 25) break;}}/////////////////////////////////////////////////////////////////////中点Bresenham算法画直线(0<=k<=1) //// //// //// /////////////////////////////////////////////////////////////////////void BresenhamLine(GLsizei x0, GLsizei y0, GLsizei x1, GLsizei y1, GLsizei num){glColor3f(1.0f,0.0f,0.0f);if(num == 1)printf("中点Bresenham算法画直线各点坐标及判别式的值\n");else if(num==0)return;//画线算法的实现GLsizei p=0;GLfloat UpIncre,DownIncre,x,y,d,k,dx,dy;if(x0>x1){x=x1;x1=x0;x0=x;y=y1;y1=y0;y0=y;}x=x0;y=y0;dx=x1-x0;dy=y1-y0;k=dy/dx;if(k>=0&&k<=1){d=dx-2*dy;UpIncre=2*dx-2*dy;DownIncre=-2*dy;while(x<=x1){putpixel(x,y);if (p>=num-1) {printf("x=%d,y=%d\n", x, y);break;}p++;x++;if(d<0){y++;d+=UpIncre;}else d+=DownIncre;}}if(k>1){d=dy-2*dx;UpIncre=2*dy-2*dx;DownIncre=-2*dx;while(y<=y1){putpixel(x,y);if (p>=num-1) {printf("x=%d,y=%d\n", x, y);break;}p++;y++;if(d<0){x++;d+=UpIncre;}else d+=DownIncre;}}if(k<0&&k>=-1){d=dx-2*dy;UpIncre=-2*dy;DownIncre=-2*dx-2*dy;while(x<=x1){putpixel(x,y);if (p>=num-1) {printf("x=%d,y=%d\n", x, y);break;}p++;x++;if(d>0){y--;d+=DownIncre;}else d+=UpIncre;}}if(k<-1){d=-dy-2*dx;UpIncre=-2*dx-2*dy;DownIncre=-2*dx;while(y>=y1){putpixel(x,y);if (p>=num-1) {printf("x=%d,y=%d\n", x, y);break;}p++;y--;if(d<0){x++;d+=UpIncre;}else d+=DownIncre;}}}/////////////////////////////////////////////////////////////////////改进的Bresenham算法画直线(0<=k<=1) //// //// x1,y1 终点坐标 //// /////////////////////////////////////////////////////////////////////void Bresenham2Line(GLsizei x0, GLsizei y0, GLsizei x1, GLsizei y1, GLsizei num) {glColor3f(1.0f,0.0f,0.0f);GLsizei x,y,dx,dy,e,k;if(num == 1)printf("改进的Bresenham算法画直线各点坐标及判别式的值\n");else if(num==0)return;//画线算法的实现GLsizei p=0;if(x0>x1){x=x1;x1=x0;x0=x;y=y1;y1=y0;y0=y;}dx=x1-x0;dy=y1-y0;k=dy/dx;if(k>=0&&k<=1){e=-dx;x=x0;y=y0;while(x<=x1){putpixel(x,y);if (p>=num-1) {printf("x=%d,y=%d\n", x, y);break;}p++;x++;e=e+2*dy;if(e>0){y++;e=e-2*dx;}}}if(k>1){e=-dy;x=x0;y=y0;while(y<=y1){putpixel(x,y);if (p>=num-1) {printf("x=%d,y=%d\n", x, y);break;}p++;y++;e=e+2*dx;if(e>0){x++;e=e-2*dy;}}}if(k<0&&k>=-1){e=-dx;x=x0;y=y0;while(x<=x1){putpixel(x,y);if (p>=num-1) {printf("x=%d,y=%d\n", x, y);break;}p++;x++;e=e+2*dy;if(e<0){y--;e=e+2*dx;}}}if(k<-1){e=-dy;x=x0;y=y0;while(y>=y1){putpixel(x,y);if (p>=num-1) {printf("x=%d,y=%d\n", x, y);break;}p++;y--;e=e-2*dx;if(e<0){x++;e=e-2*dy;}}}}///////////////////////////////////////////////////////////Bresenham算法画圆 //// //// //// ///////////////////////////////////////////////////////////void CirclePoint(GLsizei x,GLsizei y){ putpixel(x,y);putpixel(x,-y);putpixel(y,-x);putpixel(-y,-x);putpixel(-x,-y);putpixel(-x,y);putpixel(-y,x);putpixel(y,x);}void BresenhamCircle(GLsizei x, GLsizei y, GLsizei R, GLsizei num) {glColor3f(1.0f,0.0f,0.0f);GLsizei d;x=0;y=R;d=1-R;if(num == 1)printf("Bresenham算法画圆:各点坐标及判别式的值\n");else if(num==0)return;while(x<=y){CirclePoint(x,y);if (x>=num-1) {printf("x=%d,y=%d,d=%d\n", x, y,d);break;}if(d<0)d+=2*x+3;else{d+=2*(x-y)+5;y--;}x++;}}void Bresenham2Circle(GLsizei a,GLsizei b,GLsizei num){glColor3f(1.0f,0.0f,0.0f);if(num==1)printf("Bresenham算法画椭圆:各点坐标及判别式的值\n");else if(num==0)return;GLsizei x,y;float d1,d2;x=0;y=b;d1=b*b+a*a*(-b+0.5);putpixel(x,y); putpixel(-x,-y);putpixel(-x,y);putpixel(x,-y);while(b*b*(x+1)<a*a*(y-0.5)){if (x>=num-1) {printf("x=%d,y=%d,d1=%d\n", x, y,d1);break;}if(d1<=0){d1+=b*b*(2*x+3);x++;}else{d1+=b*b*(2*x+3)+a*a*(-2*y+2);x++;y--;}putpixel(x,y); putpixel(-x,-y);putpixel(-x,y);putpixel(x,-y);}//while上半部分d2=b*b*(x+0.5)*(x+0.5)+a*a*(y-1)*(y-1)-a*a*b*b;while(y>0){if (x>=num-1) {printf("x=%d,y=%d,d2=%d\n", x, y,d2);break;}if(d2<=0){d2+=b*b*(2*x+2)+a*a*(-2*y+3);x++;y--;}else{d2+=a*a*(-2*y+3);y--;}putpixel(x,y); putpixel(-x,-y);putpixel(-x,y);putpixel(x,-y);}}//初始化窗口void Initial(void){// 设置窗口颜色为蓝色glClearColor(0.0f, 0.0f, 1.0f, 1.0f);}// 窗口大小改变时调用的登记函数void ChangeSize(GLsizei w, GLsizei h){if(h == 0) h = 1;// 设置视区尺寸glViewport(0,0, w, h);// 重置坐标系统glMatrixMode(GL_PROJECTION);glLoadIdentity();// 建立修剪空间的范围if (w <= h)glOrtho (-250.0f, 250.0f, -250.0f, 250.0f*h/w, 1.0, -1.0);elseglOrtho (-250.0f, 250.0f*w/h, -250.0f, 250.0f, 1.0, -1.0);}// 在窗口中绘制图形void ReDraw(void){//用当前背景色填充窗口glClear(GL_COLOR_BUFFER_BIT);//画出坐标线DrawCordinateLine();switch(m_DrawMode){case 1:DDACreateLine(0,0,20,15,m_PointNumber);break;case 2:BresenhamLine(0,0,-20,15,m_PointNumber);break;case 3:Bresenham2Line(1,1,8,6,m_PointNumber);break;case 4:BresenhamCircle(0,0,20,m_PointNumber);break;case 5:Bresenham2Circle(10,8,m_PointNumber);default:break;}glFlush();}//设置时间回调函数void TimerFunc(int value){if(m_PointNumber == 0)value = 1;m_PointNumber = value;glutPostRedisplay();glutTimerFunc(500, TimerFunc, value+1);}//设置键盘回调函数void Keyboard(unsigned char key, int x, int y) {if (key == '1') m_DrawMode = 1;if (key == '2') m_DrawMode = 2;if (key == '3') m_DrawMode = 3;if (key == '4') m_DrawMode = 4;if (key == '5') m_DrawMode = 5;m_PointNumber = 0;glutPostRedisplay();}//void main(void)int main(int argc, char* argv[]){glutInit(&argc, argv);//初始化GLUT库OpenGL窗口的显示模式glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);glutInitWindowSize(600,600);glutInitWindowPosition(100,100);glutCreateWindow("基本图元绘制程序);glutDisplayFunc(ReDraw);glutReshapeFunc(ChangeSize);glutKeyboardFunc(Keyboard);//键盘响应回调函数glutTimerFunc(500, TimerFunc, 1);// 窗口初始化Initial();glutMainLoop(); //启动事件处理循环return 0;}。
计算机图形学实验一:画直线
贵州大学实验报告学院:计算机科学与技术专业:计算机科学与技术班级:计科131如果 d<0,则M在理想直线下方,选右上方P1点;如果 d=0,则M在理想直线上,选P1/ P2点。
由于d是xi和yi的线性函数,可采用增量计算提高运算效率。
1.如由pi点确定在是正右方P2点(d>0).,则新的中点M仅在x方向加1,新的d值为:d new=F(xi+2,yi+0.5)=a(xi+2)+b(yi+0.5)+c而 d old=F(xi+1,yi+0.5)=a(xi+1)+b(yi+0.5)+cd new=d old+a= d old-dy2.如由pi点确定是右上方P1点(d<0),则新的中点M在x和y方向都增加1,新的d值为d new=F(xi+2,yi+1.5)=a(xi+2)+b(yi+1.5)+c而 d old=F(xi+1,yi+0.5)=a(xi+1)+b(yi+0.5)+cd new=d old+a+b= d old-dy+dx在每一步中,根据前一次第二迭中计算出的d值的符号,在正右方和右上方的两个点中进行选择。
d的初始值: d0=F(x0+1,y0+0.5)=F(x0,y0)+a+b/2=a+b/2=-dy+dx/2 F(x0,y0)=0,(x0,y0)在直线上。
为了消除d的分数,重新定义 F(x,y)=2(ax+by+c)则每一步需要计算的d new 是简单的整数加法dy=y1-y0,dx=x1-x0d0=-2dy+dxd new=d old-2*dy,当 d old>=0d new=d old-2(dy-dx),当d old<0Bresenham画线算法算法原理:与DDA算法相似,Bresenham画线算法也要在每列象素中找到与理想直线最逼近的象素点。
根据直线的斜率来确定变量在x或y方向递增一个单实验内容#include"stdafx.h"#include<glut.h>#include<iostream>#include<cmath>#include<stdio.h>using namespace std;void init(){glClearColor(1.0, 1.0, 1.0, 1.0);glMatrixMode(GL_PROJECTION);glLoadIdentity();gluOrtho2D(0.0, 200.0, 0.0, 150.0);}void IntegerBresenhamline(){int x1 = 10, y1 = 10, x2 = 150, y2 = 100;int dx = abs(x2 - x1);int dy = abs(y2 - y1);int x, y;int e = -dx;if (x1 > x2){x = x2;y = y2;x2 = x1;}else{x = x1;y = y1;}glClear(GL_COLOR_BUFFER_BIT);glColor3f(1.0, 0.0, 0.0);glBegin(GL_LINES);glVertex2i(x, y);while (x < x2){if (e >= 0){y++;e = e - 2 * dx;}glVertex2i(x, y);x++; e += 2 * dy;}glEnd();glFlush();}void MidPointLine(){int x, y, x1 = 10, y1 = 10, x2 = 150, y2 = 100;int dy = y1 - y2;int dx = x2 - x1;int d = 2 * dy + dx;int dx1 = 2 * dy;int dx2 = 2 * (dx + dy);if (x1 > x2){x = x2;y = y2;x2 = x1;}else{x = x1;y = y1;}glClear(GL_COLOR_BUFFER_BIT);glColor3f(1.0, 0.0, 0.0);glBegin(GL_LINES);glVertex2i(x, y);while (x < x2){if (d<0){y++; x++;d += dx2;}else{x++, d += dx1;}glVertex2i(x, y);}glEnd();glFlush();}int main(int argc, char** argv){glutInit(&argc, argv);glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);glutInitWindowPosition(50, 100);glutInitWindowSize(400, 300);int choice;printf("输入你想画的直线 0代表Bresenham 1代表中点画线\n");while (1){scanf("%d", &choice);switch (choice){case 0:glutCreateWindow("Bresenham Draw Line");init();glutDisplayFunc(IntegerBresenhamline);glutMainLoop();break;case 1:glutCreateWindow("middle Point Line");init();glutDisplayFunc(MidPointLine);glFlush();glutMainLoop();break;default:printf("输入有误,请重新输入\n");break;}}return 0;}实验总结通过这次试验我对于中点生成算法和Bresenham生成算法有了进一步的了解,在平时上课的基础上对计算机图形学有了更深的认识,同时对课程内容也更加了解。
计算机图形学直线三种算法
计算机图形学直线三种算法1.实验⽬的:a)通过实验,进⼀步理解直线段扫描转换的DDA算法、中点画线⾃算法及bresenham算法的基本原理,掌握以上算法⽣成直线段的基本过程。
b)通过编程,掌握在C/C++环境下完成⽤DDA算法、中点画线算法及bresenham算法对任意直线段的扫描转换,以及在C/C++环境下完成⽤中点画圆及椭圆的绘制⽅法。
2. 实验内容:a)阅读《openGL三维程序设计》(电⼦书)第⼆部分第四章,掌握OpenGL基本建模⽅法,并调试其中程序。
b)参考教材第6章,编程实现整数DDA算法、中点画线法和Bresenham画线法,绘制直线(直线宽度和线型可⾃定)。
2.1 DDA直线⽣成:2.1.1 算法原理:DDA直线⽣成算法描述:1)给定⼀直线起始点(x0,y0)和终点(x1,y1)。
分别计算dx=x1-x0,dy=y1-y0。
2)计算直线的斜率k=dy/dx。
当|k|<1时转向3);当|k|<=1时,转向4);3)当x每次增加1时,y增加k。
即(xi,yi)→(xi+1,yi+k)。
直到xi增加到x1。
并且每次把得到的坐标值利⽤系统函数扫描显⽰出来。
但要注意对y坐标要进⾏int(y+0.5)取整运算。
结束。
4)对y每次增加1时,x增加1/k,即(xi,yi)→(xi+1/k,yi+1)。
直到yi增加到y1. 并且每次把得到的坐标值利⽤系统函数扫描显⽰出来。
但要注意对x坐标要进⾏int(x+0.5)取整运算。
结束。
2.1.2算法流程:2.1.3算法实现关键代码:#include#includevoid Init(){glClearColor(1.0,1.0,1.0,0.0);glMatrixMode(GL_PROJECTION);gluOrtho2D(0.0,200.0,0.0,150.0);}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(fabs(dx)>fabs(dy))steps=fabs(dx);elsesteps=fabs(dy);xIncrement=float(dx)/float(steps); N Y Start n=0X(n)<=X(End) Draw(x(n),y(n)) X(n+1)=x(n)+1 Y(n+1)=y(n)+k N=n+1 End yIncrement=float(dy)/float(steps);for(k=0;k{x+=xIncrement;y+=yIncrement;glBegin(GL_POINTS);glVertex2i(x,(int)(y+0.5));glEnd();}glFlush();}void myDisplay(void){glClear(GL_COLOR_BUFFER_BIT);glColor3f(1.0,0.0,0.0);lineDDA(50,50,100,120);}int main(int argc,char** argv){glutInit(&argc,argv);glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB); glutInitWindowPosition(100,100);glutInitWindowSize(400,400);glutCreateWindow("Hello World");Init();glutDisplayFunc(myDisplay);glutMainLoop();return 0;2.1.4算法实验结果:2.2 Bresenham直线⽣成:2.2.1 算法原理:算法基本思想:此⽅法建⽴在第⼆中⽅法的前提上,只是对此有些变化⽽已。
中点画线算法
讲授者:曲 毅
计算机图形学 图形扫描转换 直线扫描转换 中点画线算法
在
在
VS 纸
上
画一条连接点P0(1,扫 转1)描 换和P1(5,3)的直线段
屏
幕 上
(连续的)
(离散的)
就是要找出显示平面上最佳逼近
中点法 理想直线的那些象素的坐标值,
并将这些象素置成所要求的颜色
算法原理
条件背景
过点(x0,y0)、(x1, y1)的直线段L的方程为 F(x, y)=ax+by+c=0,其中,
F(M)=0
Pu与Pd的中点M(xp+1,yp+0.5)
判别方法
F(M)的符号作为判别的依据
F(M)<0
F(M)<0时,点M在直线下方,取M上方点Pu 为下一个象素点 F(M)>0时,点M在直线上方,取M下方点Pd为下一个象素点 F(M)=0时,点M在直线上,取Pu 或Pd均可,默认取Pd为下一个象素点
a=y0-y1, b=x1-x0, c=x0y1-x1y0 假定直线斜率k在0~1之间(x方向
步进1,求y的取值)
Pu(xp+1,yp+1)
F(M)>0
当前象素点为P (xp,yp)
下一个象素点有两种可选择点
Pu(xp+1,yp+1),Pd(xp+1,yp)
M(xp+1,yp+0.5) P(xp,yp) Pd(xp+1,yp)
实现过程
x
y
d
0
0
1
1
0
-3
2
1
3
3
1
-1
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
计算机图形学实验报告
班级:软件1102
姓名:***
学号:************
中点算法的线段光栅化
一、设计思想和算法流程
1.假定直线斜率0<K<1
假定直线斜率0<K<1,且已确定点亮象素点P (X p ,Y p ),则下一个与直线最接近的像素只能是P1点或P2点。
设M 为中点,Q 为交点,现需确定下一个点亮的象素。
当M 在Q 的下方-> P 2离直线更近更近->取P 2 。
M 在Q 的上方-> P 1离直线更近更近->取P 1
M 与Q 重合, P 1、P 2任取一点。
问题:如何判断M 与Q 点的关系?
由常识知:若y=kx+b;
F(x,y)=y-kx-b;则有 ()()()⎪⎩⎪⎨⎧<>=点在直线下方
0,点在直线上方0,点在直线上面0,y x F y x F y x F
假设直线方程为:ax +by +c=0 (y=(-a/b)x-c/b)
通过两点不能唯一确定a,b,c,
取 a=y 0-y 1, b=x 1-x 0, c=x 0y 1-x 1y 0
F(x,y)=ax +by +c=b(y-(-a/b)x-c/b); ()()()⎪⎩⎪⎨⎧<>=点在直线下方0,点在直线上方0
,点在直线上面0,y x F y x F y x F
则有
∴欲判断M 点是在Q 点上方还是在Q 点下方,只需把M 代入F (x ,y ),并检查它的符号。
构造判别式:d=F(M)=F(x p +1,y p +0.5)=a(x p +1)+b(y p +0.5)+c
当d<0,M 在直线(Q 点)下方,取右上方P 2;
当d>0,M 在直线(Q 点)上方,取右方P 1;
当d=0,选P 1或P 2均可,约定取P 1;
能否采用增量算法呢?若d ≥0 ---->M 在直线上方->取P1;此时再下一个象素的判别式为 d 1=F(x p +2, y p +0.5)
=a(x p +2)+b(y p +0.5)+c
= a(x p +1)+b(y p +0.5)+c +a
=d+a ;
增量为a
若d<0 ------>M 在直线下方->取P2;此时再下一个象素的判别式为 d 2= F(x p +2, y p +1.5)
=a(x p +2)+b(y p +1.5)+c
= a(x p +1)+b(y p +0.5)+c +a +b
=d+a+b ;
增量为a+b
画线从(x0, y0)开始,d的初值d0=F(x0+1, y0+0.5)= a(x0 +1)+b(y0 +0.5)+c= F(x0, y0)+a+0.5b = a+0.5b
由于只用d 的符号作判断,为了
d来摆脱小数,提高效率。
2.斜率不在[0,1]的直线的处理
设起点和终点分别为(x0,y0)和
(x1,y1)
若k>1则(y0,x0)和(y1,x1)所确定的
直线斜率k€ [0,1],适用于前面讨
论的情形。
对(y0,x0)和(y1,x1)所确
定的直线进行扫描转换,每确定
一组(x,y),输出(y,x)。
若-1<k<0
先对(x0,-y0)和(x1,-y1)所确定的直线进行扫描转换,每确定一组(x,y),输出(x,-y)。
若k<-1对(-y0,x0)和(-y1,x1)所确定的直线进行扫描转换,每确定一组(x,y),输出(y,-x)。
二、编程实现
#include<gl/glut.h>
#include<stdlib.h>
#include<stdio.h>
#include<iostream>
using namespace std;
int a1, a2, b1, b2, x, y, m;
void main(int argc, char**argv)
{
cout << "第一个点横坐标:";
cin >> a1;
cout << "第二个点横坐标:";
cin >> a2;
cout << "第一个点纵坐标:";
cin >> b1;
cout << "第二个点纵坐标:";
cin >> b2;
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
glutCreateWindow("201109020221 夏明轩光栅直线");
glClearColor(0.0, 0.0, 0.0, 0.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, 500.0, 0.0, 500.0);
if (a1<a2&&b1<b2)
{
x = 2 * (b2 - b1);
y = 2 * (b2 - b1) - 2*(a2 - a1); m = 2 * (b2 - b1) - (a2 - a1); }
else if (a1<a2&&b1>b2)
{
x = 2 * (b1 - b2);
y = 2 * (b1 - b2) - 2*(a2 - a1); m = 2 * (b1 - b2) - (a2 - a1); }
else if (a1>a2&&b1<b2)
{
x = 2 * (b2 - b1);
y = 2 * (b2 - b1) - 2*(a1 - a2); m = 2 * (b2 - b1) - (a1 - a2); }
else if (a1>a2&&b1>b2)
{
x = 2 * (b1 - b2);
y = 2 * (b1 - b2) - 2*(a1 - a2); m = 2 * (b1 - b2) - (a1 - a2); }
do
{
glColor3f(1.0, 1.0, 1.0);
glBegin(GL_POINTS);
glVertex2i(x, y);
if (a1<a2&&b1<b2)
{
a1++;
if (m<0)
m = m + x;
else
m = m + y;
b1++;
}
else if (a1<a2&&b1>b2)
{
a1++;
if (m<0)
m = m + x;
else
m = m + y;
b1--;
}
else if (a1>a2&&b1<b2)
{
a1--;
if (m<0)
m = m + x;
else
m = m + y;
b1++;
}
else if (a1>a2&&b1>b2)
{
a1--;
if (m<0)
m = m + x;
else
m = m + y;
b1--;
}
else if (a1 = a2&&b1>b2) {
b1++;
}
else
{
b1--;
}
} while (a1!=a2 | b1!=b2);
glEnd();
glutMainLoop();
}
三、运行结果
四、结论
这次试验有很大收获,首先加深了对书上几种算法画直线、画圆的理解;其次,对OpenGL 的运用熟练了很多,清楚了OpenGL 写程序的大致框架,一些典型OpenGL 语句的意义及运用都熟悉了很多。
在这次的图形学作业中,使我了解了图形界面的编程基础,也对VC 中的MFC 有了一定的了解,这会使得我能继续深入的了解VC 中的其它的部分,使我了解编写图
形界面也会带来乐趣。