2023年计算机图形学实验报告新编_第1页
2023年计算机图形学实验报告新编_第2页
2023年计算机图形学实验报告新编_第3页
2023年计算机图形学实验报告新编_第4页
2023年计算机图形学实验报告新编_第5页
已阅读5页,还剩23页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

实验一直线与圆的绘制

(一)实验目的

掌握用Besenham法编程实现直线和圆的绘制。会编程绘制虚线、点划线和具

有一定宽度的直线。

(二)实验内容

用实现直线和圆的绘制

基本规定:

(1)数据输入项为:直线的起点与终点坐标,圆心坐标与半径

(2)直线与圆输出在中

附加规定:

(1)通过用户输入可改变直线的线型(实线、虚线与点划线)

(2)通过用户输入可改变直线的线宽(用方刷子解决)

(3)通过用户输入可改变直线和圆的颜色

(三)实验所用仪表及设备

使用实验室提供的PC机。使用VisualC++编程。

(四)实验环节

1.设计思绪

1)设计对话框类

2)设计菜单

3)设计CMydrawView类

数据成员

protected:

doublex0,y0,x1,yl,R;〃直线始点与终点、圆的半

intcx,cy;//圆的坐标;

成员函数

voidMybline();//直线中点Bresenham函数

voidCirclePoint(doublex,doubley);/〃l分子画圆子

函数

voidMbcircle();〃圆中点Bresenham函数

4)程序代码

voidCMydrawView::Mybline()//中点Bresenham函数

(

SCCIientDCdc(this);

(3COLORREFrgb=RGB(0,255,0);//定义直线颜色为蓝色

0doubIex,y,d,k,t:

x=x0;y=y0;

0

if(abs(xl-xO)<le-6)

(

if(yl<yO)

(

0t=y0;yO=yl;y1=t;

00)

0for(x=x0,y=y0;y<=y1;y++)

0de.SetPixel(ROUND(x),ROUND(y),rgb);

else

{

0k=(yl-yO)/(xl-x0);d=0.5-k;

if(k>1)

00Sif(y1<y0)

St=yO;y0=y1;yl=t;

S00t=x0;x0=xl;x1=t:

m}

00d=l-0.5*k;

目for(x=xO/y=y0;y<=y1;y++)

00de.SetPixel(ROUND(x),ROUND(y),rgb);

团if(d>=O)

a0{

00X++;

0013d+=1—k;0

00}

13else

0{

0d+=1;

000}

S)

)

raf(0<=k&&k<=l)

醛if(xO>xl)

0{

但00t=xO;x0=x1;xl=t;

团t=yO;y0=y1;yl=t;

TO}

Sd=0.5-k;

03Sfor(x=x0,y=yO;x<xl;x++)

SS(

dc.SetPixelfROUND(x),ROUND(y),rgb);

B0

0if(d<0)

0{

0y++;

国团d+=1—k;

00)

03团else

d-=k;

000)

团)

函if(k>=-l&&k<0)

团团if(x0>xl)

000t=xO;xO=x1;xl=t;

励团t=yO;y0=y1;y1=t;

0)

0d=-O.5-k;

00for(x=x0zy=yO;x<xl;x++)

团团;

dc.SetPixel(ROUND(x),ROUND(y)zrgb)

00(3if(d>0)

00{

团y-;

0d—=l-k;

m)

由else

E0d-=-k;

000}

)

if(k<-l)

团if(yO<y1)

000{

团随t=y0;yO=yl;yl=t;

0t=x0;xO=xl;xl=t;

}

000d=-1-0.5—k;

团for(x=x0,y=y0;y>yl;y--)

m(

0dc.SetPixel(ROUND(x),ROUND(y),rgb);

函if(d<0)

0图{

团团x++;

0003d-=l+k;

团)

团00eIse

目函d-=1;

0}

回}

)

)

voidCMydrawView::OnMenuitem32772()〃直线菜单函数

(

//TODO:Addyourcommandhandlercodehere

InputDIgdig;

if(dlg.DoModal()==IDOK)

0{

团x0=dlg.m_x0;

xl=dlg.m_x1;

国y0=d1g.m_y0;

0yl=dlg.m_yl;

0)

AfxGetMainWnd()->SetWindowText("基本图形扫描转换:Mybline");

//RedrawWindow();

0Mybline();

voidCMydrawView::Mbcirc1e()〃圆中点Bresenham函数

(

0doub1ex,y,d;

d=l.25—R;x=0;y=R;

0for(x=O;x<y;x++)

(

但Circ1ePoint(x,y);

团if(d<0)

图d+=2*x+3;

Seise

回{

0d+=2*(x—y)+5;

y-;

}

01

)

voidCMydrawView::CircIePoint(doub1ex,doubley)〃八分子画圆函数

(

CCIientDCdc(this);

COLORREFrgb=RGB(0,0,255);

Sdc.SetPixel(ROUND(x)+cx,ROUND(y)+cy,rgb);

dc.SetPixe1(ROUND(y)+cx,ROUND(x)+cy,rgb);

dc.SetPixel(-ROUND(y)+cxzROUND(x)+cy,rgb);

Sdc.SetPixe1(ROUNDfx)+cx,-ROUND(y)+cy,rgb);

0dc.SetPixel(-ROUND(x)+cxROUND(y)+cy,rgb);

dc.SetPixel(-ROUND(y)+cx,-ROUND(x)+cy,rgb);

dc.SetPixe1(ROUND(y)+cx,—ROUND(x)+cy,rgb);

dc.SetPixe1(—ROUND(x)+cx,ROUND(y)+cyjgb);

)

voidCMydrawView::OnMENUITEMCircle()//圆菜单函数

(

//TODO:Addyourcommandhandlercodehere

circleDIgdig;

0if(dlg.DoModal()==lDOK)

0{

R=dIg.m_r;

0cx=dlg.m_ex;

cy=dlg.m_cy;

)

AfxGetMainWnd()->SetWindowText("基本图形扫描转换:Mbcirc1e");

Mbcircle();

)

voidCMydrawView::OnMENUITEMclear()〃清屏菜单函数

{

//TODO:Addyourcommandhand1ercodehere

SRedrawWindow();

}

5)运营结果

直线:

(五)思考题

如何修改程序使其适合于当直线斜率大于一或小于零时的情况?

答:分组讨论大于一和小于零的情况,分别计算机d的值,程序如下:

if(k>1)

。{oif(yl<yO)

a{<>t=yO;y0=y1;y1=t;

”=xO;xO=xl;x1=t?}

d=1-0.5*k;

。for(x=xO,y=yO;y<=y1;y++)

。(vdc.SetPixel(R0UND(x),ROUND(y),rgb);

。if(d>=0)

{flx++;

。。d+=l-k?®}

gelse

2{d+=1;0Jo)®)

if(k>=-l&&k<0)

。{if(x0>x1)

Ofijot=x0:xO=x1:xl=t;

qt=y0;y0=yl;yl=t;}

gd=-0.5-k:

。ofor(x=x0,y=y0;x<xl;x++)

{«dc.SetPixel(ROUND(x),ROUND(y),rgb);

if(d>0)

。。o(j-=1-k;)

。。else

°°d-=-k;。})

“f(kv-1)

。。{if(y0<yl)

。。{t=y0;y0=yl;yl=t;

。t=x0;x0=xl;xl=t)

。d=-l-0.5-k;

。for(x=x0,y=y0;y>i:y—)

。皿。dc.SetPixel(ROUND(x),ROUND(y),rgb);

。。if(d<0)

。。{x++;

。ad-=l+k;o)

。else

00d-=1;o}。}

实验二图形的裁剪

一、实验目的

掌握用编码法裁剪二维线段及逐边裁剪算法裁剪多边形的编程方法,并实现之。

二、实验内容'

用编码法裁剪二维线段用逐边裁剪算法裁剪多边形

基本规定:(1)数据输入项为:裁剪窗口四条边坐标

对于编码法裁剪二维线段要输入线段的起点与终点x,y坐标。

对于逐边裁剪算法裁剪多边形要输入多边形的顶点数及各顶

点x,y坐标。

(2)裁剪前与裁剪后的结果输出在活动窗口中。

附加规定:对于裁剪多边形可由用户控制裁剪的边逐边裁剪。

三、实验所用仪表及设备

使用实验室提供的PC机。使用VisualC++编程。

四、实验环节

1.编码法裁剪二维线段

己知线段端点的区域码,就可以判断直线与裁剪窗口之间的关系。

1001彳10

0001J

0010

01000110

(1)假如两端点的编码均为0000,直线在窗口内。

(2)假如两端点的编码相与不为0000,表达直线在窗口外。

(3)否则对端点编码,根据从右到左(或从左到右)顺序判别编码位是否为1,拟定与窗

口求交的边界并求出交点,裁剪线段,将交点作为直线的新端点,反复以上(1)(2)环节。

例如上图直线:

a.左端点1的编码0101,右端点2的编码1010o

b.符合(3),计算交点。

c.设从左端点开始,由于1号端点的编码为0101,从左边开始,第一位是1,所以与左

边界有交点,求交点3。

d.计算3号点的编码为0000o

e.3号点与2号点的关系仍符合(3)。

f.由于3号点的编码为0000,已在窗口内,再从右端2号点开始计算交点,由于2号

端点的编码为1010,从左边开始,第二位是1,所以与右边界有交点,求交点4,其编

码为1000。

g.3号点与4号点的关系仍符合(3)。

h.由于4号端点的编码为1000,从左边开始,第四位是1,所以与上边界有交点,求交

点5,其编码为0000。

i.3号点与5号点的关系符合(1),结束。

Cohen-SutherLand裁剪算法伪程序如下:

#defineLEFT1//0001,左

#defineRIGHT2//0010,右

#defineBOTTOM4//0100,下

#defineTOP8//I000,上

//已知端点坐标(x,y),求其所在区的编码odeo

2.设计思绪

a)设计菜单函数

直线菜单函数

裁剪菜单函数

b)设计绘画窗口

装载位图函数

定义画笔绘制窗口

定义画笔绘制直线

c)设计裁剪函数

d)设计端点编码函数

3.程序主代码

//MyCutView.cpp:imp1ementationoftheCMyCutViewclass

//

#include"stdafx.h"

#inc1ude"MyCut.h"

#include"MyCutDoc.h"

#inelude"MyCutView.h"

#defineROUND(a)int(a+0.5)

#ifdef_DEBUG

#definenewDEBUGNEW

#undcfTHIS_FILE

staticcharTHIS_HLE[]=_FILE_;

#endif

#defineLEFT1

#defineRIGHT2

#defineBOTTOM4

#defineTOP8

////////////////////////////////////////////////////III//////////////////////

//CMyCutView

IMPLEMENT.DYNCREATE(CMyCutView,CView)

BEGIN_MESSAGE_MAP(CMyCutView,CView)

//{(AFX_MSG_MAP(CMyCutView)

»ON_COMMAND(ID_MENUITEMdraw1ine,OnMENUITEMdraw1ine)

ON_COMMAND(ID_MENUITEMclip,OnMENUITEMclip)

ON_WM_LBUTTONDOWN()

ON_WM_MOUSEMOVE()

。//}}AFX_MSG_MAP

//Standardprintingcommands

ON_COMMAND(ID_FILE_PRINT,CView::OnFilePrint)

»ON_COMMAND(ID_FILE_PRINT_DIRECT,CView::OnFi1ePrint)

»ON_COMMAND(1D_FILE_PRINT_PREVIEW,CView::OnFilePrintPreview)

END_MESSAGE_MAP()

/////////////////////////////num/muim///////////////////////////////

//CMyCutViewconstruction/destruction

CMyCutView::CMyCutView()

(

//TOD0:addconstructioncodehere

wx1=200;wxr=850;wyb=200;wyt=450;

“n_attatch=FALSE;

m_i=0;

®m_draw=FALSE;

RC0=0;RCl=0;

)

CMyCutView::-CMyCutView()

{

)

OOLCMyCutView::PreCreateWindow(CREATESTRUCT&cs)

(

。//TODO:ModifytheWindowclassorstylesherebymodifying

“/theCREATESTRUCTcs

returnCView::PreCreateWindow(cs);

)

////Illi/〃/〃/〃/〃〃〃/〃/〃///〃/〃〃〃〃〃/〃/〃///////////////////HUH

//CMyCutViewdrawing

voidCMyCutView::OnDraw(CDC*pDC)

(

CMyCutDoc*pDoc=GetDocument();

«ASSERT_VALID(pDoc);

。〃TOD0:adddrawcodefornativedatahere

//装载位图

oCRectRect;

GetC11611证(:1(&1^。0;〃获得客户区的大小

«>CBitmapBitmap,*pBitmap;

^Bitmap.LoadBitmap(IDB_BITMAP1);。

CDCMemDC;

oMemDC.CreateCompatibleDC(GetDC());

叩Bitmap=MemDC.Select0bject(&Bitmap):

MemDC.BitBlt(O,O,Rect.Width(),Rect.Height(),&Picture,0,0,SRCCOPY);。

MemDC.TextOut((wxl+wxr)/2,wyb-20J窗口)〃窗口标题

。//绘制窗口和直线

CPenPen3,*pO1dPen3;//定义3个像素宽度的画笔

®Pen3.CreatePen(PS_SOLID,3,RGB(0,0,0));

pOldPen3=MemDC.Se1ectObject(&Pen3);

®MemDC.MoveTo(wx1,wyt);MemDC.LineTo(wxr,wyt);

McmDC.LineTo(wxr,wyb);McmDC.LincTo(wxl,wyb);

oMemDC.LineTo(wxl,wyt);McmDC.Se1ec10bject(pO1dPen3);

Pen3.DeleteObject();

CPenPenl,*pOIdPenl;〃定义1个像素宽度的画笔

oPenl.CreatePen(PS_SOLID,1,RGB(0,0,255));

pOldPenl=MemDC.SelectObject(&Pen1);

◎if(m_i>=1)

(

emDC.MoveTo(ROUND(Pointx[0]),ROUND(Pointy[0])):

ooMemDC.LineTo(ROUND(Pointx[1]),ROUND(Pointy[l]));。

)

oMemDC.Se1ectObject(pOldPen1);

Pen1.DeleteObject。;。

«CDC*dc=GetDC();

dc->BitBlt(0,0,Rect.Width。,Rect.Height(),&MemDC,0,0,SRCCOPY);

oMemDC.Selec(Object(pBitmap);

}

//////////////////////////////////////////////////〃/////〃/〃/〃/〃〃/////〃

//CMyCutViewprinting

BOOLCMyCutView::OnPreparePrinting(CPrintinfo*pInfo)

<>//defaultpreparation

rctumDoPreparePrinting(plnfo);

)

voidCMyCutView::OnBeginPrinting(CDC*/*pDC*/,CPrintlnfo*/*plnfo*/)

{

//TODO:addextrainitializationbeforeprinting

)

voidCMyCutView::OnEndPrinting(CDC*/*pDC*/,CPrintlnfo*/*plnfo*/)

{

//TODO:addcleanupafterprinting

)

///////////////III///////////////////////////Hllllllllllllllllllllll////////

//CMyCutViewdiagnostics

#ifdef_DEBUG

voidCMyCutView::AssertValid()const

(

»CView::AssertValid();

)

voidCMyCutView::Dump(CDumpContext&de)const

®CView::Dump(dc);

)

CMyCutDoc*CMyCutView::GetDocumcnt()//non-dcbugversionisin1ine

(

ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMyCutDoc)));

«return(CMyCutDoc*)m_pDocument;

)

#endif//.DEBUG

111/1//〃/〃/〃〃//////////////IIHU//////////////////////////////〃////////

//CMyCutViewmessagehandlers

voidCMyCutView::OnMENUITEMdrawline()

(

//TODO:Addyourcommandhand1ercodehere

if(FALSE==m_attatch)

(

^Picture,CreateCompatib1eDC(GetDC());

oCBitmap*Bitmap,*pBitmap;

aBitmap=newCBitmap;

。//Bitmap—>LoadBitmap(IDB_BITMAPl);

8PBitmap=Picture.SelectObject(Bitinap);

®m_attatch=TRUE;

)

m_draw=TRUE;

®m_i=0;

olnvalidate(FALSE);

◎AfxGetMainWnd()->SetWindowText(MCohen-Sutherland直线裁剪算法");〃显示标题

oMessageBox("请使用鼠标在屏幕上绘制直线,然后点击裁剪按钮进行裁剪“,“提醒”,MB_OKCANC

EL);

。}

voidCMyCutView::OnMENUITEMclip()//裁剪菜单函数

(

。〃TODO:Addyourcommandhandlercodehere

Cut();

Inva1idate(FALSE);

I

voidCMyCutView::OnLButtonDown(UINTnFlags,CPointpoint)

(

“/TOD0:Addyourmessagehand1ercodehereand/orca1Idefau1t

0

Af(TRUE==m_draw)

if(m_i<2)

Pointx[m_i]=point.x;Pointy[m_i]=point.y;

。,m_i++;

°}

)

«CView::OnLButtonDown(nF1ags,point);

)

voidCMyCutView::OnMouseMove(UINTnFlags,CPointpoint)

{

//TODO:Addyourmessagehandlercodehereand/orca11default

if(TRUE==m_draw)

。if(m_i<2)

{

。Pointx[m_i]=point.x;Pointy[m_i]=point.y;

oginva1idate(FALSE);

)

^CView::OnMouseMove(nFlags,point);

voidCMyCutView::Cut()

BOOLChange;

«doub1ex,y;

oRC0=EnCode(Pointx[0],Pointy[0]);

RC1=EnCode(Pointx[l],Pointy[1]);

while(TRUE)

。{

。Change=FALSE;

if(0==(RCO|RC1))

。{〃简取之

areturn;

00j

-elseif(0!=(RC0&RC1))

{〃简弃之

return;

)

eIse

if(O==RC0)//假如PO点在窗口内,互换PO和Pl,保证pO点在窗口外

〃互换点的坐标值

。doubleTPointx,TPointy;

®TPointx=Pointx[0];TPointy=Pointy[0];

。oPointx[0]=Pointx[l];Pointy[0]=Pointy[1];

wPointx[l]=TPointx:Pointy[l]=TPointy;

。。。//互换点的编码值

。unsignedintTRC;

。TRC=RC0;RCO=RC1;RC1=TRC;

O0)

。〃按左、右、下、上的顺序裁剪

gif(RC0&LEFT)〃P0点位于窗口的左侧

0»(

8x=wx1;〃求交点y

。y=Pointy[O]+(Pointy[l]-Pointy[0])*(x-Pointx[0])/(Pointx[1]-Pointx[0]);

。ePointx[0]=x;Pointy[O]=y;

。Change=TRUE;

«ORC0=EnCode(Pointx[0],Pointy[0]);RCl=EnCode(Pointx[1],Pointy[1]);

0}g

-if(RC0&RIGHT)//PO点位于窗口的右侧

ggx=wxr;〃求交点y

。。y=Pointy[0]+(Pointy[1]-Pointy[0])*(x-Pointx[0])/(Pointx[l]-Pointx[0]);

ePointx[0]=x;Pointy[0]=y;

。。Change=TRUE;

oRC0=EnCode(Pointx[0],Pointy[01);RC1=EnCode(Pointx[1],Pointy[1]);

j8

。oif(RCO&BOTTOM)〃P0点位于窗口的下侧

0(

8oy=wyb:〃求交点

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论