计算机图形学实验(3-6)

  • 格式:doc
  • 大小:310.00 KB
  • 文档页数:23

1 实验三:区域填充

一、实验目的

区域填充是指先将区域内的一点(常称为种子点)赋予给定颜色,然后将这种颜色扩展到整个区域内的过程。区域填充技术广泛应用于交互式图形、动画和美术画的计算机辅助制作中。本实验采用递归填充算法或扫描线算法实现对光栅图形的区域填充。通过本实验,可以掌握光栅图形编程的基本原理和方法。

二、实验内容

掌握光栅图形的表示方法,实现种子算法或扫描线算法。通过程序设计实现上述算法。建议采用VC++实现OpenGL程序设计。

三、实验原理、方法和手段

递归算法

在要填充的区域内取一点(X,Y)的当前颜色记为oldcolor,用要填充的颜色newcolor去取代,递归函数如下:

procedure flood-fill(X,Y,oldcolor,newcolor:integer);

begin

if getpixel(framebuffer,x,y)=oldcolor

then begin

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继续执行。

四、实验组织运行要求

本实验采用集中授课形式,每个同学独立完成上述实验要求。 2 五、实验条件

每人一台计算机独立完成实验。

六、实验步骤、结果及部分代码

(1)将图形显示在初始位置。

(2)给定种子点的坐标。

(3) 显示从种子点开始的扩散过程。

(4) 显示填充后的图形。

3 部分代码

// 填充Dlg.cpp : implementation file

//

#include "stdafx.h"

#include "填充.h"

#include "填充Dlg.h"

#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE

static char THIS_FILE[] = __FILE__;

#endif

/////////////////////////////////////////////////////////////////////////////

// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog

{

public:

CAboutDlg();

// Dialog Data

//{{AFX_DATA(CAboutDlg)

enum { IDD = IDD_ABOUTBOX };

//}}AFX_DATA

4 // ClassWizard generated virtual function overrides

//{{AFX_VIRTUAL(CAboutDlg)

protected:

virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support

//}}AFX_VIRTUAL

// Implementation

protected:

//{{AFX_MSG(CAboutDlg)

//}}AFX_MSG

DECLARE_MESSAGE_MAP()

};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)

{

//{{AFX_DATA_INIT(CAboutDlg)

//}}AFX_DATA_INIT

}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)

{

CDialog::DoDataExchange(pDX);

//{{AFX_DATA_MAP(CAboutDlg)

//}}AFX_DATA_MAP

}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)

//{{AFX_MSG_MAP(CAboutDlg)

// No message handlers

//}}AFX_MSG_MAP

END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////

// CMyDlg dialog

CMyDlg::CMyDlg(CWnd* pParent /*=NULL*/)

: CDialog(CMyDlg::IDD, pParent)

{

//{{AFX_DATA_INIT(CMyDlg)

// NOTE: the ClassWizard will add member initialization here

//}}AFX_DATA_INIT

// Note that LoadIcon does not require a subsequent DestroyIcon in Win32

m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

num = 0;

col = RGB(0,0,0);

ldb = FALSE;

step = 0; 5 }

void CMyDlg::DoDataExchange(CDataExchange* pDX)

{

CDialog::DoDataExchange(pDX);

//{{AFX_DATA_MAP(CMyDlg)

// NOTE: the ClassWizard will add DDX and DDV calls here

//}}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()

/////////////////////////////////////////////////////////////////////////////

// CMyDlg message handlers

BOOL CMyDlg::OnInitDialog()

{

CDialog::OnInitDialog();

// Add "About..." menu item to system menu.

// IDM_ABOUTBOX must be in the system command range.

ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);

ASSERT(IDM_ABOUTBOX < 0xF000);

CMenu* pSysMenu = GetSystemMenu(FALSE);

if (pSysMenu != NULL)

{

CString strAboutMenu;

strAboutMenu.LoadString(IDS_ABOUTBOX);

if (!strAboutMenu.IsEmpty())

{

pSysMenu->AppendMenu(MF_SEPARATOR);

pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);