4.2.3 程序实现与上机实习(二)
一、实验目的
编写圆和椭圆的扫描转换算法程序,验证算法的正确性。
二、实验任务
1. 编写中点画圆法的扫描转换程序,考虑原点在(x0,y0)处程序的改动;
2. 添加鼠标程序,实现交互式画圆;
3. 编写中点画椭圆法的扫描转换程序;
4. 添加鼠标程序,实现交互式画椭圆;
三、实验内容
1.编写中点画圆法的扫描转换程序,考虑原点在(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,y+x0), 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)
算法程序如下:
MidpointCircle(int x0,int y0,int r, int color)
{
int x,y;
float d;
x=0;y=r;d=1.25-r;
CirPot(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(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));
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)
{
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) 编译、运行程序,查看结果。
任务2:添加鼠标程序,实现交互式画圆
在任务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)向视图类中添加自定义的成员函数原型:
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
"math.h"
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)
{
CPoint prePnt,curPnt;
prePnt=m_bR; //获得鼠标所在的前一位置
curPnt=point;
//绘制橡皮筋线
m_r=ComputeRadius(m_bO,prePnt);
MidpointCircle(pDC,m_bO.x,m_bO.y,m_r,RGB(255,0,0));//用异或模式重复画圆,擦出所画的圆
// DrawCircle(pDC,m_bO,prePnt);
m_r=ComputeRadius(m_bO,curPnt);
MidpointCircle(pDC,m_bO.x,m_bO.y,m_r,RGB(255,0,0));
//用当前位置作为圆周上的点画圆
m_bR=point;
}
pDC->SetROP2(nDrawmode);
//恢复原绘图模式
ReleaseDC(pDC);
//释放设备环境
CView::OnMouseMove(nFlags, point);
}