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

提交評論