案例2直线中点Bresenham算法.docx
- 文档编号:8279146
- 上传时间:2023-01-30
- 格式:DOCX
- 页数:14
- 大小:36.09KB
案例2直线中点Bresenham算法.docx
《案例2直线中点Bresenham算法.docx》由会员分享,可在线阅读,更多相关《案例2直线中点Bresenham算法.docx(14页珍藏版)》请在冰豆网上搜索。
案例2直线中点Bresenham算法
课程实验报告
课程名称
计算机图形学
班级
实验日期
姓名
学号
实验成绩
实验名称
直线中点Bresenham算法
实
验
目
的
及
要
求
斜率0≤k≤1直线的中点Bresenham算法。
任意斜率直线段绘制算法。
颜色类的定义与调用方法。
直线类的定义与调用方法。
鼠标按键消息映射方法。
实
验
内
容
1、案例描述
在屏幕客户区内按下鼠标左键赞扬直线的起点,移动鼠标指针到直线终点上,弹起鼠标左键绘制任意斜率的直线段。
2、功能说明
(1)设计CRGB类其成员变量为double型的红绿蓝分量red,green和blue,将red,green和blue分量分别规范到[0,1]区间。
(2)设计Cline直线类,其成员变量为直线段的起点坐标P0和终点坐标P1,成员函数为MoveTo()和LineTo()函数。
(3)Cline类的LineTo()函数使用中点Bresenham算法绘制任意斜率的直线段,包括k=±∞,k>1,
0≤𝑘≤1,-1≤𝑘<0和k<-1这5种情况。
(4)自定义屏幕二维坐标系,原点位于客户区中心,x轴水平向右为正,y轴垂直向上为正。
直线段的起点坐标和终点坐标相对于屏幕客户区中心定义。
算
法
描
述
及
实
验
步
骤
1、案例分析
MFC提供的CDC类的成员函数MoveTo()和LineTo()函数用于绘制傻任意斜率的直线段,直线段的颜色由所选用的画笔指定。
MoveTo()函数移动当前点到参数(x,y)所指定的点,不画线;LineTo()函数从当前点画一直线段到参数(x,y)所指定的点,但不包括(x,y)。
本案例通过定义Cline类来模拟CDC类绘制任意斜的直线段,采用直线中点Bresenham算法。
2、算法设计
对于0≤𝑘≤1的直线段,中点Bresenham算法如下:
(1)使用鼠标选择起点坐标p0(x0,y0)和终点坐标p1(x1,y1)。
要求起点的的坐标小于等于终点的x坐标。
(2)定义直线段当前点坐标x,y,定义中点误差项d,定义直线斜k,定义像素点颜色clr。
(3)x=x0,y=y0,计算d=0.5-k,k=(y1-y0)/(x1-x0),
clr=CRGB(0,0,1)
(4)绘制点(x,y),判断d的符号。
若d<0,则(x,y)更新为(x+1,y+1),d更新为d+1-k;否则(x,y)更新为(x+1,y),d更新为d-k。
(5)如果当前点x 3、设计CRGB类 为了规范颜色的处事,定义了CRGB类,重载了“+”,“-”、“*”、“\”、“+=”、“-=”、“*=”、“/=”运算符。 成员函数Normalize()将颜色分量red,green,blue规范到[0,1]闭区间内。 RGB.h #pragmaonce classCRGB { public: CRGB(); CRGB(double,double,double); ~CRGB(); friendCRGBoperator+(constCRGB&,constCRGB&); friendCRGBoperator-(constCRGB&,constCRGB&); friendCRGBoperator*(constCRGB&,constCRGB&); friendCRGBoperator*(constCRGB&,double); friendCRGBoperator*(double,constCRGB&); friendCRGBoperator/(constCRGB&,double); friendCRGBoperator+=(constCRGB&,constCRGB&); friendCRGBoperator-=(constCRGB&,constCRGB&); friendCRGBoperator*=(constCRGB&,constCRGB&); friendCRGBoperator/=(constCRGB&,double); voidNormalize(); public: doublered; doublegreen; doubleblue; }; RGB.cpp #include"stdafx.h" #include"RGB.h" CRGB: : CRGB() { red=1.0; green=1.0; blue=1.0; } CRGB: : ~CRGB() {} CRGB: : CRGB(doubler,doubleg,doubleb) { red=r; green=g; blue=b; } CRGBoperator+(constCRGB&c1,constCRGB&c2) { CRGBc; c.red=c1.red+c2.red; c.green=c1.green+c2.green; c.blue=c1.blue+c2.blue; returnc; } CRGBoperator-(constCRGB&c1,constCRGB&c2) { CRGBc; c.red=c1.red-c2.red; c.green=c1.green-c2.green; c.blue=c1.blue-c2.blue; returnc; } CRGBoperator*(constCRGB&c1,constCRGB&c2) { CRGBc; c.red=c1.red*c2.red; c.green=c1.green*c2.green; c.blue=c1.blue*c2.blue; returnc; } CRGBoperator*(constCRGB&c1,doublek) { CRGBc; c.red=c1.red*k; c.green=c1.green*k; c.blue=c1.blue*k; returnc; } CRGBoperator*(doublek,constCRGB&c1) { CRGBc; c.red=c1.red*k; c.green=c1.green*k; c.blue=c1.blue*k; returnc; } CRGBoperator/(doublek,constCRGB&c1) { CRGBc; c.red=c1.red/k; c.green=c1.green/k; c.blue=c1.blue/k; returnc; } CRGBoperator+=(constCRGB&c1,constCRGB&c2) { CRGBc; c.red=c1.red+c2.red; c.green=c1.green+c2.green; c.blue=c1.blue+c2.blue; returnc; } CRGBoperator-=(constCRGB&c1,constCRGB&c2) { CRGBc; c.red=c1.red-c2.red; c.green=c1.green-c2.green; c.blue=c1.blue-c2.blue; returnc; } CRGBoperator*=(constCRGB&c1,constCRGB&c2) { CRGBc; c.red=c1.red*c2.red; c.green=c1.green*c2.green; c.blue=c1.blue*c2.blue; returnc; } CRGBoperator/=(constCRGB&c1,doublek) { CRGBc; c.red=c1.red/k; c.green=c1.green/k; c.blue=c1.blue/k; returnc; } voidCRGB: : Normalize() { red=(red<0.0)? 0.0: ((red>1.0)? 1.0: red); green=(green<0.0)? 0.0: ((green>1.0)? 1.0: green); blue=(blue<0.0)? 0.0: ((blue>1.0)? 1.0: blue); } 4、设计Cline直线类 定义直线绘制任意斜率的直线,其成员函数为MoveTo()和LineTo()。 Line.h #pragmaonce #include"P2.h" #include"RGB.h" classCLine { public: CLine(); virtual~CLine(); voidMoveTo(CDC*,CP2);//移动到指定位置 voidMoveTo(CDC*,double,double); voidLineTo(CDC*,CP2);//绘制直线,不含终点 voidLineTo(CDC*,double,double); public: CP2P0;//起点 CP2P1;//终点 }; Line.cpp #include"stdafx.h" #include"Line.h" #include"math.h" #defineRound(d)int(floor(d+0.5))//四舍五入宏定义 #ifdef_DEBUG #undefTHIS_FILE staticcharTHIS_FILE[]=__FILE__; #definenewDEBUG_NEW #endif CLine: : CLine() {} CLine: : ~CLine() {} voidCLine: : MoveTo(CDC*pDC,CP2p0)//绘制直线起点函数 { P0=p0; } voidCLine: : MoveTo(CDC*pDC,doublex0,doubley0)//重载函数 { P0=CP2(x0,y0); } voidCLine: : LineTo(CDC*pDC,CP2p1) { P1=p1; CP2p,t; CRGBclr=CRGB(0.0,0.0,0.0);//黑色像素点 if(fabs(P0.x-P1.x)<1e-6)//绘制垂线 { if(P0.y>P1.y)//交换顶点,使得起始点低于终点 { t=P0;P0=P1;P1=t; } for(p=P0;p.y { pDC->SetPixelV(Round(p.x),Round(p.y),RGB(clr.red*255,clr.green*255,clr.blue*255)); } } else { doublek,d; k=(P1.y-P0.y)/(P1.x-P0.x); if(k>1.0)//绘制k>1 { if(P0.y>P1.y) { t=P0;P0=P1;P1=t; } d=1-0.5*k; for(p=P0;p.y { pDC->SetPixelV(Round(p.x),Round(p.y),RGB(clr.red*255,clr.green*255,clr.blue*255)); if(d>=0) { p.x++; d+=1-k; } else d+=1; } } if(0.0<=k&&k<=1.0)//绘制0<=k<=1 { if(P0.x>P1.x) { t=P0;P0=P1;P1=t; } d=0.5-k; for(p=P0;p.x { pDC->SetPixelV(Round(p.x),Round(p.y),RGB(clr.red*255,clr.green*255,clr.blue*255)); if(d<0) { p.y++; d+=1-k; } else d-=k; } } if(k>=-1.0&&k<0.0)//绘制-1<=k<0 { if(P0.x>P1.x) { t=P0;P0=P1;P1=t; } d=-0.5-k; for(p=P0;p.x { pDC->SetPixelV(Round(p.x),Round(p.y),RGB(clr.red*255,clr.green*255,clr.blue*255)); if(d>0) { p.y--; d-=1+k; } else d-=k; } } if(k<-1.0)//绘制k<-1 { if(P0.y { t=P0;P0=P1;P1=t; } d=-1-0.5*k; for(p=P0;p.y>P1.y;p.y--) { pDC->SetPixelV(Round(p.x),Round(p.y),RGB(clr.red*255,clr.green*255,clr.blue*255)); if(d<0) { p.x++; d-=1+k; } else d-=1; } } } P0=p1; } voidCLine: : LineTo(CDC*pDC,doublex1,doubley1)//重载函数 { LineTo(pDC,CP2(x1,y1)); } 5、添加鼠标消息映射 添加WM_LBUTTONDOWN消息映射函数 voidCTestView: : OnLButtonDown(UINTnFlags,CPointpoint) { //TODO: 在此添加消息处理程序代码和/或调用默认值 p0.x=point.x; p0.y=point.y; p0.x=p0.x-rect.Width()/2;//设备坐标系向自定义坐标系转换 p0.y=rect.Height()/2-p0.y; CView: : OnLButtonDown(nFlags,point); } 添加WM_LBUTTONUP消息映射函数 voidCTestView: : OnLButtonUp(UINTnFlags,CPointpoint) { //TODO: 在此添加消息处理程序代码和/或调用默认值 p1.x=point.x; p1.y=point.y; CLine*line=newCLine; CDC*pDC=GetDC(); //定义设备上下文指针 //与案例比新加的语句 GetClientRect(rect); pDC->SetMapMode(MM_ANISOTROPIC);//自定义坐标系 pDC->SetWindowExt(rect.Width(),rect.Height());//设置窗口比例 pDC->SetViewportExt(rect.Width(),-rect.Height());//设置视区比例,且x轴水平向右,y轴垂直向上 pDC->SetViewportOrg(rect.Width()/2,rect.Height()/2);//设置客户区中心为坐标系原点 rect.OffsetRect(-rect.Width()/2,-rect.Height()/2);//矩形与客户区重合 /*pDC->MoveTo(0,0); pDC->LineTo(100,200);*/ p1.x=p1.x-rect.Width()/2; p1.y=rect.Height()/2-p1.y; line->MoveTo(pDC,p0); line->LineTo(pDC,p1); deleteline; ReleaseDC(pDC); CView: : OnLButtonUp(nFlags,point); } 调 试 过 程 及 实 验 结 果 总 结 本案例实现的Cline类的成员函数类似于CDC类的MoveTo()函数和LineTo()函数,用于绘制任意斜的直线段。 MSDN指出CDC类的LineTo()函数画一段直线到终点坐标位置,但不包括终点坐标。 CLine类的LineTo()函数实现了该功能。 本案例映射了WM_LBUTTONDOWN消息来确定直线段的起点坐标,映射了WM_LBUTTONDOWN消息来确定直线段的终点坐标并绘制直线段。 本次实验帮助我更好的了解了图形学的理论知识,锻炼了我的动手能力。 实验地点 9层机房 指导教师 李丽亚
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 案例 直线 中点 Bresenham 算法
![提示](https://static.bdocx.com/images/bang_tan.gif)