计算机图形学实验指导书(9)

2019-09-01 23:26

B.圆、椭圆生成算法 一、实验目的

编写圆和椭圆的扫描转换算法程序,验证算法的正确性。

二、实验任务(2学时)

1. 编写中点画圆法的扫描转换程序,考虑原点在(x0,y0)处程序的改动; 2. 添加鼠标程序,实现交互式画圆; 3. 编写中点画椭圆法的扫描转换程序; 4. 添加鼠标程序,实现交互式画椭圆;

三、实验内容

圆的Bresenham算法

设圆的半径为r。先考虑圆心在(0, 0),并从x=0、y=r,开始的顺时针方向的1/8圆周的生成过程。在这种情况下,x每步增加1,从x=0开始,到x=y结束。即有 xi+1 = xi + 1

相应的yi+1则在两种可能中选择: yi+1 = yi或者yi+1 = yi-1 选择的原则是考察精确值y是靠近yi还是 靠近yi-1(如右图), 计算式为 y2 = r2-(xi+1)2

d1 = yi2-y2 = yi2-r2+(xi+1)2

d2 = y2-(yi-1)2 = r2-(xi+1)2-(yi-1)2 令pi=d1-d2,并代入d1、d2,则有 pi = 2(xi+1)2 + yi2 + (yi-1)2-2r2

pi称为误差。如果pi<0则yi+1=yi,否则yi+1=yi-1。 pi的递归式为

pi+1 = pi + 4xi +6+2(yi+12- yi2) -2(yi+1-yi) pi的初值由上式代入xi=0,yi=r而得 p1 = 3-2r

根据上面的推导,圆周生成算法思想如下: ⒈ 求误差初值,p1=3-2r,i=1,画点(0, r);

⒉ 求下一个光栅位置,其中xi+1=xi+1,如果pi<0则yi+1=yi,否则yi+1=yi-1; ⒊ 画点(xi+1, yi+1);

⒋ 计算下一个误差,如果pi<0则pi+1=pi+4xi+6,否则pi+1=pi+4(xi-yi)+10; ⒌ i=i+1,如果x=y则结束,否则返回步骤2。

-- 37

任务一:中点画圆法的扫描转换算法

编写中点画圆法的扫描转换程序,考虑原点在(x0,y0)处程序的改动;

分析:考虑圆心不在原点,设圆心坐标为(x0,y0)。通过平移坐标原点到圆心,则第二个8分圆上一点p(x,y),其原始坐标为 x’=x+x0 y’=y+y0

即p’1(x0 +x, y+y0)

其它7个对称点分别是:p’2(x0+y,y0+x), p’3 (x0+y,y0-x),p’4 (x0+x,y0-y),p’5 (x0-x,y0-y),p’6 (x0-y,y0-x),p’7 (x0-y,y0+x),p’8 (x0-x,y0+y)

p’1(x0 +x, y0+y) Y’ Y 算法程序如下:

p(x,y)

MidpointCircle(int x0,int y0,int r, int color) p’8 (x0-x,y0+y) R {

p’2(x0+y,y0+x) int x,y; p’7 (x0-y,y0+x) float d;

(x0,y0) X’ x=0; y=r ; d=1.25-r ;

p’6 (x0-y,y0-x) CirPot(x0,y0,x,y,color); p’3 (x0+y,y0-x) while (x<=y)

p’4 (x0+x,y0-y)) { p’5 (x0-x,y0-y) if(d<0)

O(0,0) X {

d+=2*x+3; x++; }

(x0+R,y0)

else {

d+=2*(x-y)+5; x++; y--; }

CirPot(x0,y0,x,y,color); } /* while*/

} /* MidpointCiecle */

int CirPot(int x0,int y0,int x,int y,int color) {

Setpixel((x0+x),(y0+y)); Setpixel((x0+y),(y0+x)); Setpixel((x0+y),(y0-x)); Setpixel((x0+x),(y0-y)); Setpixel((x0-x),(y0-y)); Setpixel((x0-y),(y0-x)); Setpixel((x0-y),(y0+x));

-- 38

Setpixel((x0-x),(y0+y)); }

程序实现步骤:

(1) 建立MidPointCircle工程文件;

(2) 右击CMidPointCircleView类,建立成员函数

void MidpointCircle(CDC *pDC,int x0, int y0, int r, COLORREF color) int CirPot(CDC *pDC,int x0, int y0, int x, int y, COLORREF color) (3) 编写成员函数代码,程序如下:

void CMidPointCircleView::MidpointCircle(CDC *pDC,int x0, int y0, int r, COLORREF color) {

int x,y; float d;

x=0;y=r;d=1.25-r;

CirPot(pDC,x0,y0,x,y,color); while (x<=y) {

if(d<0) {

d+=2*x+3; x++; } else {

d+=2*(x-y)+5; x++; y--; }

CirPot(pDC,x0,y0,x,y,color); } /* while*/ }

int CMidPointCircleView::CirPot(CDC *pDC,int x0, int y0, int x, int y, COLORREF color) {

pDC->SetPixel((x0+x),(y0+y),color); pDC->SetPixel((x0+y),(y0+x),color); pDC->SetPixel((x0+y),(y0-x),color); pDC->SetPixel((x0+x),(y0-y),color); pDC->SetPixel((x0-x),(y0-y),color); pDC->SetPixel((x0-y),(y0-x),color); pDC->SetPixel((x0-y),(y0+x),color); pDC->SetPixel((x0-x),(y0+y),color); return 0; }

(4)编写OnDraw(CDC* pDC)函数,程序如下: void CMidPointCircleView::OnDraw(CDC* pDC) {

-- 39

CMidPointCircleDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here MidpointCircle(pDC,100, 100, 10, RGB(255,0,0)); MidpointCircle(pDC,500, 300, 60, RGB(255,255,0)); }

(6) 编译、运行程序,查看结果。

任务二:添加鼠标程序,实现交互式画圆

在任务1的基础上,完成下列步骤:

(1)向视图类中添加自定义的成员变量

用鼠标右键单击视图类,选择“Add Member Variable…”,添加下面三个成员变量。 proctected :

int m_r; // 半径

CPoint m_bO; // 圆心 CPoint m_bR; //圆上的点

int m_ist; //圆心与圆周上点的区别,m_ist=0,表示鼠标左击点为圆心, //m_ist=1,表示鼠标左击点为圆周上的点

(2)在视图类CPP文件的构造函数中初始化成员变量 CMidPointCircleMouseView::CMidPointCircleMouseView() { // TODO: add construction code here m_bO.x=0; m_bO.y=0; //圆心 m_bR.x=0; m_bR.y=0; //圆上的点 m_ist=0; //圆心与圆上的点区别 m_r=0; //圆的半径 }

(3)向视图类中添加自定义的成员函数原型:

-- 40

public:

int ComputeRadius(CPoint cenp,CPoint ardp);

添加成员函数的程序代码:

int CMouseSpringView::ComputeRadius(CPoint cenp, CPoint ardp) {

int dx=cenp.x-ardp.x; int dy=cenp.y-ardp.y;

//sqrt()函数的调用,在头文件中加入#include \ return (int)sqrt(dx*dx+dy*dy); }

(4)向视图类中添加两个鼠标消息响应函数,并输入鼠标处理程序代码。

具体操作方法与鼠标示例1方法相同。一个是OnLButtonDown()函数,另一个是OnMouseMove()函数。程序如下:

void CMidPointCircleMouseView::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default CDC *pDC=GetDC();

pDC->SelectStockObject(NULL_BRUSH); if (!m_ist) //绘制圆 { m_bO=m_bR=point; //纪录第一次单击鼠标位置,定圆心 m_ist++; } else { m_bR=point; //记录第二次单击鼠标的位置,定圆周上的点 m_ist--; // 为新绘图作准备 m_r=ComputeRadius(m_bO,m_bR); MidpointCircle(pDC,m_bO.x,m_bO.y,m_r,RGB(255,0,0)); } ReleaseDC(pDC); //释放设备环境 CView::OnLButtonDown(nFlags, point); }

void CMidPointCircleMouseView::OnMouseMove(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default CDC *pDC=GetDC();

int nDrawmode=pDC->SetROP2(R2_NOT); //设置异或绘图模式,并保存原来绘图模式 pDC->SelectStockObject(NULL_BRUSH); if(m_ist==1)

-- 41


计算机图形学实验指导书(9).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:灾害地质学实习 - 图文

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: