计算机图形学实验—中点算法画直线
- 格式:docx
- 大小:338.95 KB
- 文档页数:7
计算机图形学实验报告专业:信息与计算科学班级: 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(应用程序编程接口),它实际上是一种图形与硬件的接口,包括了多个图形函数。
计算机图形学实验指导书袁科计算机技术实验中心目录实验一实现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生成算法有了进一步的了解,在平时上课的基础上对计算机图形学有了更深的认识,同时对课程内容也更加了解。
西北师范大学计算机科学与工程学院学生实验报告学号专业计算机科学与技术班级师范一班姓名课程名称计算机图形学课程类型专业限选实验名称实验一中点画直线一、实验目的: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 使用画线算法,绘制直线段一.实验目的及要求(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算法是一种很方便很实用很简单的算法,它对任意斜率的直线段具有通用性。
计算机图形学实验报告
班级:软件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 中的其它的部分,使我了解编写图
形界面也会带来乐趣。