多边形的填充实验经典.docx
《多边形的填充实验经典.docx》由会员分享,可在线阅读,更多相关《多边形的填充实验经典.docx(13页珍藏版)》请在冰点文库上搜索。
![多边形的填充实验经典.docx](https://file1.bingdoc.com/fileroot1/2023-5/10/3c35900c-d860-407c-b682-b6c343a2507a/3c35900c-d860-407c-b682-b6c343a2507a1.gif)
多边形的填充实验经典
试验
实验一:
图形的区域填充
一、实验目的
区域填充是指先将区域内的一点(常称为种子点)赋予给定颜色,然后将这种颜色扩展到整个区域内的过程。
区域填充技术广泛应用于交互式图形、动画和美术画的计算机辅助制作中。
本实验采用递归填充算法或扫描线算法实现对光栅图形的区域填充。
通过本实验,可以掌握光栅图形编程的基本原理和方法。
二、实验内容
掌握光栅图形的表示方法,实现种子算法或扫描线算法。
通过程序设计实现上述算法。
建议采用VC++实现OpenGL程序设计。
三、实验原理、方法和手段
递归算法
在要填充的区域内取一点(X,Y)的当前颜色记为oldcolor,用要填充的颜色newcolor去取代,递归函数如下:
procedureflood-fill(X,Y,oldcolor,newcolor:
integer);
begin
ifgetpixel(framebuffer,x,y)=oldcolor
thenbegin
setpixel(framebuffer,x,y,newcolor);
flood-fill(X,Y+1,oldcolor,newcolor);
flood-fill(X,Y-1,oldcolor,newcolor);
flood-fill(X-1,Y,oldcolor,newcolor);
flood-fill(X+1,Y,oldcolor,newcolor);
end
end
扫描线算法
扫描线算法的效率明显高于递归算法,其算法的基本思想如下:
(1)(初始化)将算法设置的堆栈置为空,将给定的种子点(x,y)压入堆栈。
(2)(出栈)如果堆栈为空,算法结束;否则取栈顶元素(x,y)作为种子点。
(3)(区段填充)从种子点(x,y)开始沿纵坐标为y的当前扫描线向左右两个方向逐个象素进行填色,其值置为newcolor,直到抵达边界为止。
(4)(定范围)以xleft和xright分别表示在步骤3中填充的区段两端点的横坐标。
(5)(进栈)分别在与当前扫描线相邻的上下两条扫描线上,确定位于区间[xleft,xright]内的给定区域的区段。
如果这些区段内的象素的颜色值为newcolor或者boundarycolor(边界上象素的颜色值),则转到步骤2,否则取区段的右端点为种子压入堆栈,再转到步骤2继续执行。
四、实验组织运行要求
本实验采用集中授课形式,每个同学独立完成上述实验要求。
五、实验条件
每人一台计算机独立完成实验。
六、实验步骤、结果及部分代码
(1)将图形显示在初始位置。
(2)给定种子点的坐标。
(3)显示从种子点开始的扩散过程。
(4)显示填充后的图形。
部分代码
//填充Dlg.cpp:
implementationfile
//
#include"stdafx.h"
#include"填充.h"
#include"填充Dlg.h"
#ifdef_DEBUG
#definenewDEBUG_NEW
#undefTHIS_FILE
staticcharTHIS_FILE[]=__FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
//CAboutDlgdialogusedforAppAbout
classCAboutDlg:
publicCDialog
{
public:
CAboutDlg();
//DialogData
//{{AFX_DATA(CAboutDlg)
enum{IDD=IDD_ABOUTBOX};
//}}AFX_DATA
//ClassWizardgeneratedvirtualfunctionoverrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtualvoidDoDataExchange(CDataExchange*pDX);//DDX/DDVsupport
//}}AFX_VIRTUAL
//Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg:
:
CAboutDlg():
CDialog(CAboutDlg:
:
IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
voidCAboutDlg:
:
DoDataExchange(CDataExchange*pDX)
{
CDialog:
:
DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg,CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
//Nomessagehandlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
//CMyDlgdialog
CMyDlg:
:
CMyDlg(CWnd*pParent/*=NULL*/)
:
CDialog(CMyDlg:
:
IDD,pParent)
{
//{{AFX_DATA_INIT(CMyDlg)
//NOTE:
theClassWizardwilladdmemberinitializationhere
//}}AFX_DATA_INIT
//NotethatLoadIcondoesnotrequireasubsequentDestroyIconinWin32
m_hIcon=AfxGetApp()->LoadIcon(IDR_MAINFRAME);
num=0;
col=RGB(0,0,0);
ldb=FALSE;
step=0;
}
voidCMyDlg:
:
DoDataExchange(CDataExchange*pDX)
{
CDialog:
:
DoDataExchange(pDX);
//{{AFX_DATA_MAP(CMyDlg)
//NOTE:
theClassWizardwilladdDDXandDDVcallshere
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CMyDlg,CDialog)
//{{AFX_MSG_MAP(CMyDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON4,OnButton4)
ON_BN_CLICKED(IDC_BUTTON1,OnButton1)
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
ON_BN_CLICKED(IDC_BUTTON2,OnButton2)
ON_BN_CLICKED(IDC_BUTTON3,OnButton3)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
//CMyDlgmessagehandlers
BOOLCMyDlg:
:
OnInitDialog()
{
CDialog:
:
OnInitDialog();
//Add"About..."menuitemtosystemmenu.
//IDM_ABOUTBOXmustbeinthesystemcommandrange.
ASSERT((IDM_ABOUTBOX&0xFFF0)==IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX<0xF000);
CMenu*pSysMenu=GetSystemMenu(FALSE);
if(pSysMenu!
=NULL)
{
CStringstrAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if(!
strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING,IDM_ABOUTBOX,strAboutMenu);
}
}
//Settheiconforthisdialog.Theframeworkdoesthisautomatically
//whentheapplication'smainwindowisnotadialog
SetIcon(m_hIcon,TRUE);//Setbigicon
SetIcon(m_hIcon,FALSE);//Setsmallicon
//TODO:
Addextrainitializationhere
CPaintDCdc(this);
pic.CreateCompatibleDC(&dc);
CBitmap*bp1,*obp1;
bp1=newCBitmap;
bp1->LoadBitmap(IDB_B);
obp1=pic.SelectObject(bp1);
obp1->DeleteObject();
returnTRUE;//returnTRUEunlessyousetthefocustoacontrol
}
voidCMyDlg:
:
OnSysCommand(UINTnID,LPARAMlParam)
{
if((nID&0xFFF0)==IDM_ABOUTBOX)
{
CAboutDlgdlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog:
:
OnSysCommand(nID,lParam);
}
}
//Ifyouaddaminimizebuttontoyourdialog,youwillneedthecodebelow
//todrawtheicon.ForMFCapplicationsusingthedocument/viewmodel,
//thisisautomaticallydoneforyoubytheframework.
voidCMyDlg:
:
OnPaint()
{
CPaintDCdc(this);//devicecontextforpainting
if(IsIconic())
{
SendMessage(WM_ICONERASEBKGND,(WPARAM)dc.GetSafeHdc(),0);
//Centericoninclientrectangle
intcxIcon=GetSystemMetrics(SM_CXICON);
intcyIcon=GetSystemMetrics(SM_CYICON);
CRectrect;
GetClientRect(&rect);
intx=(rect.Width()-cxIcon+1)/2;
inty=(rect.Height()-cyIcon+1)/2;
//Drawtheicon
dc.DrawIcon(x,y,m_hIcon);
}
else
{
CDialog:
:
OnPaint();
}
CDCmdc;
CBitmapbp,*ob;
bp.LoadBitmap(IDB_B);
mdc.CreateCompatibleDC(GetDC());
ob=mdc.SelectObject(&bp);
mdc.BitBlt(0,0,520,330,&pic,0,0,SRCCOPY);
mdc.MoveTo(mx[0],my[0]);
for(inti=1;imdc.LineTo(mx[i],my[i]);
}
if(step!
=1){
mdc.LineTo(mx[0],my[0]);
}
CDC*dc1;
CWnd*wd1;
wd1=this->GetDlgItem(IDC_S);
dc1=wd1->GetDC();
dc1->BitBlt(1,1,517,327,&mdc,0,0,SRCCOPY);
mdc.SelectObject(ob);
}
//Thesystemcallsthistoobtainthecursortodisplaywhiletheuserdrags
//theminimizedwindow.
HCURSORCMyDlg:
:
OnQueryDragIcon()
{
return(HCURSOR)m_hIcon;
}
voidCMyDlg:
:
OnButton4()
{
//TODO:
Addyourcontrolnotificationhandlercodehere
OnOK();
}
voidCMyDlg:
:
OnButton1()
{
//TODO:
Addyourcontrolnotificationhandlercodehere
if(step==1){
step=0;
SetDlgItemText(IDC_BUTTON1,"画-多¨¤边À?
形?
");
Invalidate(FALSE);
}
else{
num=0;
step=1;
ldb=FALSE;
SetDlgItemText(IDC_BUTTON1,"绘?
制?
完ª¨º毕À?
");
CDCmdc;
CBitmapbmp,*obp;
bmp.LoadBitmap(IDB_B);
mdc.CreateCompatibleDC(GetDC());
obp=mdc.SelectObject(&bmp);
pic.BitBlt(0,0,520,330,&mdc,0,0,SRCCOPY);
mdc.SelectObject(obp);
Invalidate(FALSE);
}
}
voidCMyDlg:
:
OnLButtonDown(UINTnFlags,CPointpoint)
{
//TODO:
Addyourmessagehandlercodehereand/orcalldefault
if(step==1&&point.x>11&&point.x<529&&point.y>11&&point.y<339){
if(num<49){
ldb=TRUE;
if(!
num){
mx[num]=point.x-12;
my[num]=point.y-12;
num++;
}
num++;
//Invalidate(FALSE);
}
}
CDialog:
:
OnLButtonDown(nFlags,point);
}
voidCMyDlg:
:
OnLButtonUp(UINTnFlags,CPointpoint)
{
//TODO:
Addyourmessagehandlercodehereand/orcalldefault
if(ldb){
ldb=FALSE;
mx[num-1]=point.x-12;
my[num-1]=point.y-12;
Invalidate(FALSE);
}
CDialog:
:
OnLButtonUp(nFlags,point);
}
voidCMyDlg:
:
OnMouseMove(UINTnFlags,CPointpoint)
{
//TODO:
Addyourmessagehandlercodehereand/orcalldefault
if(ldb){
mx[num-1]=point.x-12;
my[num-1]=point.y-12;
Invalidate(FALSE);
}
CDialog:
:
OnMouseMove(nFlags,point);
}
voidCMyDlg:
:
OnButton2()
{
//TODO:
Addyourcontrolnotificationhandlercodehere
CColorDialogccd(col);
if(ccd.DoModal()==IDOK){
col=ccd.GetColor();
}
}
voidCMyDlg:
:
OnButton3()
{
//TODO:
Addyourcontrolnotificationhandlercodehere
step=0;
ldb=FALSE;
SetDlgItemText(IDC_BUTTON1,"画-多¨¤边À?
形?
");
if(num<2){
MessageBox("尚¦D未¡ä绘?
制?
多¨¤边À?
形?
!
ê?
");
return;
}
inti=0,j,k;
intb,e;
floatd,fd;
for(i=0;i各¡Â条¬?
边À?
进?
行D处ä|理¤¨ª
b=my[i];
e=my[(i+1)%num];
d=float(mx[i]-mx[(i+1)%num])/(my[i]-my[(i+1)%num]);
fd=float(mx[i]);
if(b>e){
j=b;
b=e;
e=j;
fd=float(mx[(i+1)%num]);
}
for(j=b;j条¬?
边À?
上¦?
各¡Â个?
点Ì?
//if(j==my[i]){
//k=mx[i];
//}
//else{
//k=int(float((j-my[i])*(my[(i+1)%num]-my[i]))/float(mx[(i+1)%num]-mx[i])+float(mx[i])+0.5f);
//}
k=int(fd+(j-b)*d+0.5f);
for(;k<518;k++){
if(pic.GetPixel(k,j)==col){
pic.SetPixel(k,j,RGB(255,255,255));
}
else{
pic.SetPixel(k,j,col);
}
}
}
}
Invalidate(FALSE);
}
七、实验分析
本次实验,实现了不规则图形的区域填充,达到了实验要求。
通过本实验,掌握了光栅图形编程的基本原理和方法。
为以后工作打下了基础。