📄 图形学实验dlg.cpp
字号:
}
dc.FillSolidRect(0,30,500,530,RGB(255,255,255));
int i,j;
for (i = 0; i <= 500; i++)
{
for (j = 0; j<= 500; j++)
{
pointdata[i][j] = 0;
}
}
break;
}
case 7:
{
//利用双缓冲,先在内存中将多面体画好,然后再画到屏幕上
if (isTimerOn)
{
KillTimer(1);
isTimerOn = false;
}
//创建内存画步
CDC mdc;
mdc.CreateCompatibleDC(NULL);
mybitmap.CreateCompatibleBitmap(GetDC(),500,500);
mdc.SelectObject(&mybitmap);
mdc.FillSolidRect(0,0,500,500,RGB(255,255,255));
//显示提示信息
mdc.TextOut(30,30,"按住键盘方向键可以");
mdc.TextOut(30,50,"任意角度旋转");
mdc.TextOut(30,70,"按一下 W,S,A,D 可以");
mdc.TextOut(30,90,"自动旋转");
mdc.TextOut(30,110,"按 T 可以停止旋转");
//panduankejianmian()用来判断当前状态下三个点所在的面是否是可见的
//如果可见就将其填充显示
if (PanduanKejianmian(A[0],A[4],A[1]))
{
CRgn rgn0;
CPoint psz0[3];
psz0[0] = ChangePoint(CPoint(A[0].x,A[0].y));
psz0[1] = ChangePoint(CPoint(A[1].x,A[1].y));
psz0[2] = ChangePoint(CPoint(A[4].x,A[4].y));
rgn0.CreatePolygonRgn(psz0,3,WINDING);
mdc.FillRgn(&rgn0,&mybrush[0]);
mdc.MoveTo(ChangePoint(CPoint(A[0].x,A[0].y)));
mdc.LineTo(ChangePoint(CPoint(A[4].x,A[4].y)));
mdc.LineTo(ChangePoint(CPoint(A[1].x,A[1].y)));
mdc.LineTo(ChangePoint(CPoint(A[0].x,A[0].y)));
}
if (PanduanKejianmian(A[3],A[2],A[1]))
{
CRgn rgn0;
CPoint psz0[3];
psz0[0] = ChangePoint(CPoint(A[2].x,A[2].y));
psz0[1] = ChangePoint(CPoint(A[1].x,A[1].y));
psz0[2] = ChangePoint(CPoint(A[3].x,A[3].y));
rgn0.CreatePolygonRgn(psz0,3,WINDING);
mdc.FillRgn(&rgn0,&mybrush[5]);
mdc.MoveTo(ChangePoint(CPoint(A[3].x,A[3].y)));
mdc.LineTo(ChangePoint(CPoint(A[2].x,A[2].y)));
mdc.LineTo(ChangePoint(CPoint(A[1].x,A[1].y)));
mdc.LineTo(ChangePoint(CPoint(A[3].x,A[3].y)));
}
if (PanduanKejianmian(A[0],A[2],A[3]))
{
CRgn rgn0;
CPoint psz0[3];
psz0[0] = ChangePoint(CPoint(A[0].x,A[0].y));
psz0[1] = ChangePoint(CPoint(A[2].x,A[2].y));
psz0[2] = ChangePoint(CPoint(A[3].x,A[3].y));
rgn0.CreatePolygonRgn(psz0,3,WINDING);
mdc.FillRgn(&rgn0,&mybrush[2]);
mdc.MoveTo(ChangePoint(CPoint(A[0].x,A[0].y)));
mdc.LineTo(ChangePoint(CPoint(A[2].x,A[2].y)));
mdc.LineTo(ChangePoint(CPoint(A[3].x,A[3].y)));
mdc.LineTo(ChangePoint(CPoint(A[0].x,A[0].y)));
}
if (PanduanKejianmian(A[0],A[1],A[2]))
{
CRgn rgn0;
CPoint psz0[3];
psz0[0] = ChangePoint(CPoint(A[0].x,A[0].y));
psz0[1] = ChangePoint(CPoint(A[1].x,A[1].y));
psz0[2] = ChangePoint(CPoint(A[2].x,A[2].y));
rgn0.CreatePolygonRgn(psz0,3,WINDING);
mdc.FillRgn(&rgn0,&mybrush[4]);
mdc.MoveTo(ChangePoint(CPoint(A[0].x,A[0].y)));
mdc.LineTo(ChangePoint(CPoint(A[1].x,A[1].y)));
mdc.LineTo(ChangePoint(CPoint(A[2].x,A[2].y)));
mdc.LineTo(ChangePoint(CPoint(A[0].x,A[0].y)));
}
if (PanduanKejianmian(A[0],A[3],A[4]))
{
CRgn rgn0;
CPoint psz0[3];
psz0[0] = ChangePoint(CPoint(A[0].x,A[0].y));
psz0[1] = ChangePoint(CPoint(A[3].x,A[3].y));
psz0[2] = ChangePoint(CPoint(A[4].x,A[4].y));
rgn0.CreatePolygonRgn(psz0,3,WINDING);
mdc.FillRgn(&rgn0,&mybrush[1]);
mdc.MoveTo(ChangePoint(CPoint(A[0].x,A[0].y)));
mdc.LineTo(ChangePoint(CPoint(A[3].x,A[3].y)));
mdc.LineTo(ChangePoint(CPoint(A[4].x,A[4].y)));
mdc.LineTo(ChangePoint(CPoint(A[0].x,A[0].y)));
}
if (PanduanKejianmian(A[1],A[4],A[3]))
{
CRgn rgn0;
CPoint psz0[3];
psz0[0] = ChangePoint(CPoint(A[3].x,A[3].y));
psz0[1] = ChangePoint(CPoint(A[1].x,A[1].y));
psz0[2] = ChangePoint(CPoint(A[4].x,A[4].y));
rgn0.CreatePolygonRgn(psz0,3,WINDING);
mdc.FillRgn(&rgn0,&mybrush[3]);
mdc.MoveTo(ChangePoint(CPoint(A[1].x,A[1].y)));
mdc.LineTo(ChangePoint(CPoint(A[3].x,A[3].y)));
mdc.LineTo(ChangePoint(CPoint(A[4].x,A[4].y)));
mdc.LineTo(ChangePoint(CPoint(A[1].x,A[1].y)));
}
//画到屏幕上
dc.BitBlt(0,30,500,500,&mdc,0,0,SRCCOPY);
//画完之后清除内存画布
mybitmap.DeleteObject();
mdc.DeleteDC();
break;
}
case 8:
{
//演示画家算法的思想
CDC mdc;
mdc.CreateCompatibleDC(NULL);
mybitmap.CreateCompatibleBitmap(GetDC(),500,500);
mdc.SelectObject(&mybitmap);
mdc.FillSolidRect(0,0,500,500,RGB(255,255,255));
mdc.TextOut(30,30,"画家算法由远及近地填充每个面");
mdc.TextOut(30,50,"从而实现消隐");
mdc.MoveTo(ChangePoint(CPoint(LastA[0].x,LastA[0].y)));
mdc.LineTo(ChangePoint(CPoint(LastA[1].x,LastA[1].y)));
mdc.LineTo(ChangePoint(CPoint(LastA[2].x,LastA[2].y)));
mdc.LineTo(ChangePoint(CPoint(LastA[0].x,LastA[0].y)));
mdc.LineTo(ChangePoint(CPoint(LastA[4].x,LastA[4].y)));
mdc.LineTo(ChangePoint(CPoint(LastA[1].x,LastA[1].y)));
mdc.LineTo(ChangePoint(CPoint(LastA[3].x,LastA[3].y)));
mdc.LineTo(ChangePoint(CPoint(LastA[4].x,LastA[4].y)));
mdc.MoveTo(ChangePoint(CPoint(LastA[0].x,LastA[0].y)));
mdc.LineTo(ChangePoint(CPoint(LastA[3].x,LastA[3].y)));
mdc.LineTo(ChangePoint(CPoint(LastA[2].x,LastA[2].y)));
dc.BitBlt(0,30,500,500,&mdc,0,0,SRCCOPY);
mybitmap.DeleteObject();
mdc.DeleteDC();
pshuzu[0][0] =ChangePoint(CPoint(LastA[0].x,LastA[0].y+30));
pshuzu[0][1] =ChangePoint(CPoint(LastA[1].x,LastA[1].y+30));
pshuzu[0][2] =ChangePoint(CPoint(LastA[2].x,LastA[2].y+30));
pshuzu[1][0] =ChangePoint(CPoint(LastA[0].x,LastA[0].y+30));
pshuzu[1][1] =ChangePoint(CPoint(LastA[3].x,LastA[3].y+30));
pshuzu[1][2] =ChangePoint(CPoint(LastA[2].x,LastA[2].y+30));
pshuzu[2][0] =ChangePoint(CPoint(LastA[0].x,LastA[0].y+30));
pshuzu[2][1] =ChangePoint(CPoint(LastA[4].x,LastA[4].y+30));
pshuzu[2][2] =ChangePoint(CPoint(LastA[3].x,LastA[3].y+30));
pshuzu[3][0] =ChangePoint(CPoint(LastA[1].x,LastA[1].y+30));
pshuzu[3][1] =ChangePoint(CPoint(LastA[3].x,LastA[3].y+30));
pshuzu[3][2] =ChangePoint(CPoint(LastA[2].x,LastA[2].y+30));
pshuzu[4][0] =ChangePoint(CPoint(LastA[1].x,LastA[1].y+30));
pshuzu[4][1] =ChangePoint(CPoint(LastA[4].x,LastA[4].y+30));
pshuzu[4][2] =ChangePoint(CPoint(LastA[0].x,LastA[0].y+30));
pshuzu[5][0] =ChangePoint(CPoint(LastA[3].x,LastA[3].y+30));
pshuzu[5][1] =ChangePoint(CPoint(LastA[1].x,LastA[1].y+30));
pshuzu[5][2] =ChangePoint(CPoint(LastA[4].x,LastA[4].y+30));
myrgn[0].CreatePolygonRgn(pshuzu[0],3,WINDING);
myrgn[1].CreatePolygonRgn(pshuzu[1],3,WINDING);
myrgn[2].CreatePolygonRgn(pshuzu[2],3,WINDING);
myrgn[3].CreatePolygonRgn(pshuzu[3],3,WINDING);
myrgn[4].CreatePolygonRgn(pshuzu[4],3,WINDING);
myrgn[5].CreatePolygonRgn(pshuzu[5],3,WINDING);
for (int i =0; i < 6; i++)
{
dc.FillRgn(&myrgn[i],&mybrush[i]);
Sleep(800);
}
}
default:break;
}
CDialog::OnPaint();
}
}
HCURSOR CMyDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
bool CMyDlg::PanduanKejianmian(LiTipoint a,LiTipoint b, LiTipoint c)
{
//由于视线是沿Z轴方向观察多面体,所以可以
//通过判断Ax+By+Cz+D=0方程中C的符号来判断
//面是否是可见的
double panduantiaojian;
panduantiaojian = a.x*(b.y-c.y)+b.x*(c.y-a.y)+c.x*(a.y-b.y);
if (panduantiaojian > 0.0)
{
//可见返回true
return true;
}
else
{
return false;
}
}
void CMyDlg::OnGuanyu()
{
//显示说明对话框
CShoumingDlg dlg;
dlg.DoModal();
}
//点
void CMyDlg::Onpoint()
{
//state赋值1,马上刷新
state = 1;
Invalidate();
}
void CMyDlg::changelitipoint(LiTipoint& a,char whichzhou,double cita)
{
//将三维坐标系下的点a绕坐标轴旋转,得到新的坐标
LiTipoint b ;
b.x = a.x;
b.y = a.y;
b.z = a.z;
switch(whichzhou)
{
//绕X轴旋转
case 'x':
case 'X':
{
a.y=b.y*cos(cita)-b.z*sin(cita);
a.z=b.y*sin(cita)+b.z*cos(cita);
break;
}
//Y轴
case 'y':
case 'Y':
{
a.x=b.z*sin(cita)+b.x*cos(cita);
a.z=b.z*cos(cita)-b.x*sin(cita);
break;
}
//Z轴
case 'z':
case 'Z':
{
a.x=b.x*cos(cita)-b.y*sin(cita);
a.y=b.x*sin(cita)+b.y*cos(cita);
break;
}
default:
break;
}
}
void CMyDlg::OnX30()
{
//绕X轴旋转30度
if (state == 7)
{
zhou = 'x';
for (int i = 0; i < 5; i++)
{
changelitipoint(A[i],zhou,PI/6.0);
}
Invalidate();
}
}
void CMyDlg::On2Line()
{
//点击画线命令时,将state赋值为5,刷新屏幕,等待操作
state = 5;
Invalidate();
}
void CMyDlg::On2yuan()
{
//点击画圆命令时,state赋值为6,刷新屏幕,等待操作
state = 6;
Invalidate();
}
void CMyDlg::On3duomianti()
{
//显示多面体,state= 7
state = 7;
Invalidate();
}
void CMyDlg::OnClear()
{
//清屏
state = 0;
Invalidate();
}
void CMyDlg::OnKUAIda()
{
//显示大的方块,并实现用其画线
state = 3;
Invalidate();
}
void CMyDlg::OnKUAIxiao()
{
//显示小方块,用其作为图元
state = 2;
Invalidate();
}
void CMyDlg::OnX60()
{
//绕X轴旋转60度
if (state == 7)
{
zhou = 'x';
for (int i = 0 ; i < 5; i++)
{
changelitipoint(A[i],zhou,PI/3.0);
}
Invalidate();
}
}
void CMyDlg::OnX90()
{
//绕X轴旋转90度
if (state == 7)
{
zhou = 'x';
for (int i = 0 ; i < 5; i++)
{
changelitipoint(A[i],zhou,PI/2.0);
}
Invalidate();
}
}
void CMyDlg::OnY30()
{
//绕Y旋转30度
if (state == 7)
{
zhou = 'y';
for (int i = 0 ; i < 5; i++)
{
changelitipoint(A[i],zhou,PI/6.0);
}
Invalidate();
}
}
void CMyDlg::OnY90()
{
//绕Y轴旋转90度
if (state == 7)
{
zhou = 'y';
for (int i = 0 ; i < 5; i++)
{
changelitipoint(A[i],zhou,PI/2.0);
}
Invalidate();
}
}
void CMyDlg::OnY60()
{
//绕Y旋转60度
if (state == 7)
{
zhou = 'y';
for (int i = 0 ; i < 5; i++)
{
changelitipoint(A[i],zhou,PI/3.0);
}
Invalidate();
}
}
void CMyDlg::OnYuan()
{
//显示圆,用其为图元
state = 4;
Invalidate();
}
void CMyDlg::OnExit()
{
// 计时器如果没终止,终止它
if (isTimerOn)
{
KillTimer(1);
}
//显示About对话框
CAboutDlg dlg;
dlg.DoModal();
CDialog::OnOK();
}
CPoint CMyDlg::ChangePoint(CPoint point)
{
//将点坐标转换成屏幕坐标
CPoint tempPoint ;
tempPoint.x = point.x+250;
tempPoint.y = point.y+280;
return tempPoint;
}
void CMyDlg::OnMouseMove(UINT nFlags, CPoint point)
{
//设置光标形状
::SetCursor(AfxGetApp()->LoadCursor(IDC_CURSOR1));
if (nFlags == MK_LBUTTON)
{
//如果鼠标移动的同时左键按下的话,执行操作
CClientDC dc(this);
switch(state)
{
case 1:
{
//以点为图元画线
dc.SetPixelV(point,RGB(0,0,255));
break;
}
case 2:
{
//以小方块为图元画线,需判断边界条件
int adjusty = point.y-10;
if (point.y-10<30)
{
adjusty = 30;
}
CRect myrect(point.x-10,adjusty,point.x+10,point.y+10);
CBrush mybrush;
mybrush.CreateSolidBrush(RGB(0,0,255));
dc.FillRect(myrect,&mybrush);
break;
}
case 3:
{
//以大方块为图元画线,需判断边界条件
int adjusty = point.y-20;
if (point.y-20<30)
{
adjusty = 30;
}
CRect myrect(point.x-20,adjusty,point.x+20,point.y+20);
CBrush mybrush;
mybrush.CreateSolidBrush(RGB(0,0,255));
dc.FillRect(myrect,&mybrush);
break;
}
case 4:
{
//以圆为图元画线,判断边界条件
int adjusty = point.y-10;
if (point.y-10<30)
{
adjusty = 30;
}
CBrush mybrush;
mybrush.CreateSolidBrush(RGB(0,0,255));
CRgn myrgn;
myrgn.CreateEllipticRgn(point.x-10,adjusty,point.x+10,point.y+10);
dc.FillRgn(&myrgn,&mybrush);
break;
}
case 5:
{
//DDA画线,用到双缓冲技术,避免画面闪烁
CDC memdc;
memdc.CreateCompatibleDC(NULL);
mybitmap.CreateCompatibleBitmap(GetDC(),500,500);
memdc.SelectObject(&mybitmap);
memdc.FillSolidRect(0,0,500,500,RGB(255,255,255));
//擦去上一次移动时画的线
lineDDA(pointBegin.x,pointBegin.y,pointEnd.x,pointEnd.y,RGB(255,255,255));
//恢复屏幕显示图形,避免上一步擦除了不该擦除的点
int i,j;
for (i = 0; i <= 500; i++)
{
for (j = 0; j<= 500; j++)
{
if (pointdata[i][j] == 1)
{
memdc.SetPixelV(CPoint(i,j),RGB(0,0,255));
}
}
}
dc.BitBlt(0,30,500,500,&memdc,0,0,SRCCOPY);
mybitmap.DeleteObject();
memdc.DeleteDC();
//重新画线
pointEnd = point;
lineDDA(pointBegin.x,pointBegin.y,pointEnd.x,pointEnd.y,RGB(0,0,255));
break;
}
case 6:
{
//与5类似,实现DDA画圆
CDC memdc;
memdc.CreateCompatibleDC(NULL);
mybitmap.CreateCompatibleBitmap(GetDC(),500,500);
memdc.SelectObject(&mybitmap);
memdc.FillSolidRect(0,0,500,500,RGB(255,255,255));
CPoint mypoint((CircleBeginPoint.x+CircleEndPoint.x)/2,(CircleBeginPoint.y+CircleEndPoint.y)/2);
int r;
r=sqrt((point.x-mypoint.x)*(point.x-mypoint.x)+(point.y-mypoint.y)*(point.y-mypoint.y));
CircleDDA(mypoint.x,mypoint.y,r,RGB(0,0,255));
int i,j;
for (i = 0; i <= 500; i++)
{
for (j = 0; j<= 500; j++)
{
if (pointdata[i][j] == 1)
{
memdc.SetPixelV(CPoint(i,j),RGB(0,0,255));
}
}
}
dc.BitBlt(0,30,500,500,&memdc,0,0,SRCCOPY);
mybitmap.DeleteObject();
memdc.DeleteDC();
CircleEndPoint = point;
CPoint mypoint2((CircleBeginPoint.x+CircleEndPoint.x)/2,(CircleBeginPoint.y+CircleEndPoint.y)/2);
r=sqrt((point.x-mypoint2.x)*(point.x-mypoint2.x)+(point.y-mypoint2.y)*(point.y-mypoint2.y));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -