计算机图形学画直线制作过程.docx
《计算机图形学画直线制作过程.docx》由会员分享,可在线阅读,更多相关《计算机图形学画直线制作过程.docx(17页珍藏版)》请在冰点文库上搜索。
计算机图形学画直线制作过程
本次程序是计算机图形学老师刚刚布置的一道作业,要求我们画出任意直线的点阵图。
在这里分享下制作的过程及效果,希望有兴趣各位朋友能够及时提醒我其中的不足,谢谢!
步骤:
(一)打开VC++6.0,创建一个MFCAppWizard(exe),工程名为:
jask_jd_Line,选择但文档类型,在应用程序向导第六步将基类改为“CFormView”,单击“完成”,创建完成。
(二)创建一个新对话框IDD_DLG_INPUT,用来输入直线方程。
并添加控件如下:
控件名称
控件ID
控件标题
组框
IDC_STATIC
方程式:
静态文本
IDC_STATIC
Y=
编辑框
IDC_EDIT1
静态文本
IDC_STATIC
X+
编辑框
IDC_EDIT_SEND
静态文本
IDC_EDIT2
按钮
IDOK
确定
按钮
IDCANCEL
取消
如图:
(三)用类向导为对话框IDD_DLG_INPUT创建一个新类CFuncInput,并为控件添加变量:
(四)在CFuncInput:
:
DoDataExchange(CDataExchange*pDX)函数中添加如下代码初始化对话框变量值:
(这样当弹出对话框时就编辑框中就会有初始值,当然这个也可以不要)
SetDlgItemText(IDC_EDIT1,"1");
SetDlgItemText(IDC_EDIT2,"0");
(五)打开ResourceView进入Menu项,(删除默认的菜单项,左键单机菜单主项,按Delete就可以了,但是别全部删除了,不然这个菜单会消失的,之后就是编译会出问题,在全部删除之前添加菜单“操作”,这个不用多介绍吧,如下:
IDM_DRAWLINE画线(&D)
IDM_NEW刷新(&N)
IDM_COLOR颜色(&C)
(六)用类向导为这三个菜单ID添加响应函数,并添加代码如下:
voidCTask_jd_LineView:
:
OnDrawline()
//主要的函数,根据输入的方程式进行绘制直线
{
//TODO:
Addyourcommandhandlercodehere
CFuncInputdlg;
//这里注释下,要在task_jd_LineView.h文件中添加#include"FuncInput.h"包含新建的类
if(dlg.DoModal()==IDOK)
{
floatk,c;
k=StringtoInt(dlg.m_k);
c=StringtoInt(dlg.m_c);
//这个StringtoInt是自己定义的函数,代码见后文
CDC*pDC=GetDC();
CBrushbrush(Color);
CBrush*old=pDC->SelectObject(&brush);
CRectrt;
GetClientRect(&rt);
if(k>=0&&k<=1)//斜率大于0且小于1
{
intx=-(rt.Width()/2)/10;
inty=(int)(k*x+c+0.5);
floate=k*x+c-y-0.5;
for(inti=0;i<=rt.Width()/10;i++)
{
pDC->Ellipse(rt.Width()/2+x*10-3,rt.Height()/2-y*10-3,rt.Width()/2+x*10+3,rt.Height()/2-y*10+3);
x++;
e+=k;
if(e>=0)
{
y++;
e--;
}
}
}
elseif(k>=-1&&k<0)//斜率大于-1且小于0
{
intx=-(rt.Width()/2)/10;
inty=(int)(k*x+c+0.5);
floate=k*x+c-y+0.5;
for(inti=0;i<=rt.Width()/10;i++)
{
pDC->Ellipse(rt.Width()/2+x*10-3,rt.Height()/2-y*10-3,rt.Width()/2+x*10+3,rt.Height()/2-y*10+3);
x++;
e+=k;
if(e<0)
{
y--;
e++;
}
}
}
elseif(k>1)//斜率大于1
{
inty=-(rt.Height()/2)/10;
intx=(int)((y-c)/k+0.5);
floate=(y-c)/k-x-0.5;
for(inti=0;i<=rt.Width()/10;i++)
{
pDC->Ellipse(rt.Width()/2+x*10-3,rt.Height()/2-y*10-3,rt.Width()/2+x*10+3,rt.Height()/2-y*10+3);
y++;
e+=1/k;
if(e>=0)
{
x++;
e--;
}
}
}
else//斜率小于-1
{
inty=-(rt.Height()/2)/10;
intx=(int)((y-c)/k+0.5);
floate=(y-c)/k-x+0.5;
for(inti=0;i<=rt.Width()/10;i++)
{
pDC->Ellipse(rt.Width()/2+x*10-3,rt.Height()/2-y*10-3,rt.Width()/2+x*10+3,rt.Height()/2-y*10+3);
y++;
e+=1/k;
if(e<0)
{
x--;
e++;
}
}
}
}
else
{}
}
voidCTask_jd_LineView:
:
OnNew()
{
//TODO:
Addyourcommandhandlercodehere
Invalidate();
CDC*pDC=GetDC();
CTask_jd_LineView:
:
OnDraw(pDC);
}
voidCTask_jd_LineView:
:
OnColor()
{
//TODO:
Addyourcommandhandlercodehere
CColorDialogColorDialog;//定义颜色对话框对象
if(ColorDialog.DoModal()==IDOK)
{
Color=ColorDialog.GetColor();
/*Color在classCTask_jd_LineView中定义:
Private:
COLORREFColor;并在voidCTask_jd_LineView:
:
OnInitialUpdate()中初始化为:
Color=RGB(250,0,0);*/
}
}
(七)添加函数将字符串转变成浮点数,函数如下:
floatStringtoInt(CStringstr)//将字符串转换成浮点数
{
floatresult=0;
intdot=0;
intd=10;
intsymbol=1;
for(inti=0;i{
if(str.GetAt(i)=='-')
symbol=-1;
elseif(str.GetAt(i)=='.')
{
if(dot)
break;
else
dot=1;
}
elseif(!
dot&&str.GetAt(i)>='0'&&str.GetAt(i)<='9')
result=result*10+str.GetAt(i)-'0';
elseif(str.GetAt(i)>='0'&&str.GetAt(i)<='9')
{
result+=1.0*(str.GetAt(i)-'0')/d;
d*=10;
}
else
{
AfxMessageBox("系数中有非数字符号,请核实后重新输入!
");
break;
}
}
return(symbol*result);
}
(八)对了,还有一个很重要的没说,或许应该首先就介绍的,那就是坐标系的创建,用ClassWizard创建Draw函数画坐标系:
voidCTask_jd_LineView:
:
OnDraw(CDC*pDC)//初始化坐标系
{
//TODO:
Addyourspecializedcodehereand/orcallthebaseclass
CRectrt;
GetClientRect(&rt);
Mpoint.x=rt.Width()/2;
Mpoint.y=rt.Height()/2;
//Mpoint在classCTask_jd_LineView中定义:
Private:
CPointMpoint;代表原点
/***横坐标和纵坐标(粗线)***/
CPenpen(PS_SOLID,3,RGB(0,0,255));
CPen*pOldPen=pDC->SelectObject(&pen);
pDC->MoveTo(Mpoint.x-1,0);
pDC->LineTo(Mpoint.x-1,rt.Height());
pDC->MoveTo(0,Mpoint.y-1);
pDC->LineTo(rt.Width(),Mpoint.y-1);
pDC->SelectObject(pOldPen);
/***坐标系(细线)***/
CPenpen1;
pen1.CreatePen(PS_SOLID,1,RGB(180,120,0));
pOldPen=pDC->SelectObject(&pen1);
for(inti=Mpoint.x+10;i{
pDC->MoveTo(i,0);
pDC->LineTo(i,rt.Height());
}
for(i=Mpoint.x-10;i>0;i-=10)
{
pDC->MoveTo(i,0);
pDC->LineTo(i,rt.Height());
}
for(i=Mpoint.y+10;i{
pDC->MoveTo(0,i);
pDC->LineTo(rt.Width(),i);
}
for(i=Mpoint.y-10;i>0;i-=10)
{
pDC->MoveTo(0,i);
pDC->LineTo(rt.Width(),i);
}
pDC->SelectObject(pOldPen);
}
(九)到现在为止,应该就可以运行成功了。
在我的代码里还添加了一些元素,让界面更好看:
在intCMainFrame:
:
OnCreate(LPCREATESTRUCTlpCreateStruct)中删除(工具栏):
if(!
m_wndToolBar.CreateEx(this,TBSTYLE_FLAT,WS_CHILD|WS_VISIBLE|CBRS_TOP|CBRS_GRIPPER|CBRS_TOOLTIPS|CBRS_FLYBY|CBRS_SIZE_DYNAMIC)||!
m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
{
TRACE0("Failedtocreatetoolbar\n");
return-1;//failtocreate
}
和
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndToolBar);
在BOOLCMainFrame:
:
PreCreateWindow(CREATESTRUCT&cs)中添加:
cs.lpszName=_T("绘制任意直线");
cs.style=WS_OVERLAPPEDWINDOW;
cs.cx=500;
cs.cy=400;
returnTRUE;
修改staticUINTindicators[]=
{
//ID_SEPARATOR,//statuslineindicator
//ID_INDICATOR_CAPS,
//ID_INDICATOR_NUM,
//ID_INDICATOR_SCRL,
IDS_INDICATOR_MOUSE
/*在StringTable中双击最后的空白行,添加ID:
IDS_INDICATOR_MOUSE,
标题:
“当前坐标是:
“不要忽略这些空格哈,不然没那么好看的,具体的各位自己调整*/
};
(十)用ClassWizard天机鼠标移动响应函数,并将鼠标位置所在的坐标显示在状态栏上,代码如下:
voidCTask_jd_LineView:
:
OnMouseMove(UINTnFlags,CPointpoint)//显示当前鼠标在该坐标系中的坐标
{
//TODO:
Addyourmessagehandlercodehereand/orcalldefault
CStatusBar*pFrame=(CStatusBar*)AfxGetMainWnd();
CStatusBar*pStatusBar=(CStatusBar*)pFrame->GetDescendantWindow(AFX_IDW_STATUS_BAR);
CStringstrMousePoint;
strMousePoint.Format("\t当前坐标为:
x=%1.2f,y=%1.2f",1.0*(point.x-Mpoint.x)/10,1.0*(Mpoint.y-point.y)/10);
pStatusBar->SetPaneText(pStatusBar->CommandToIndex(IDS_INDICATOR_MOUSE),strMousePoint);
CFormView:
:
OnMouseMove(nFlags,point);
}
(十一)这下真的没问题了,下面大家看看我运行的几个截图效果:
1、鼠标放上之前:
2、鼠标放上之后:
3、点击菜单“画线(&D)”后:
4、单机确定后:
5、点击菜单“刷新(&N)”后返回图2,点击菜单“颜色(&C)”后:
6、选择绿色,点击“确定”,再点击菜单“画线”,改变编辑框的内容:
7、点击“确定”后:
8、点击“颜色”选择粉红,确定,点击画线,改变对话框值:
9、点击“确定”后:
10、当然鼠标在上面移动式,状态栏的变化是没法截图过来的,就不演示了,有兴趣的做出来后就看得到了,就到此为止吧,还请多多指教!