计算机图形学3——Boundary-Fill Algorithm

图形学实验:边界填充多边形算法

算法原理如下:
种子像素入栈,当栈非空时重复执行如下三步操作:

(1)栈顶像素出栈
(2)将出栈像素置成要填充色
(3)按左、上、右、下顺序检查与栈像素相邻的四个像素,若其中某个像素不在边界且未置成填充色,则把该像素入栈

核心代码如下:

void Boundaryfill (int seedx,int seedy)
{
	CMyStack stk1;
    long color=RGB(255,0,0); //填充颜色 red
	long boundary_color=RGB(255,255,255); //边界颜色 white
	unsigned char params[4]; //保存读取的一个像素点的颜色值
	dcpt p1;
    p1.x=seedx;
	p1.y=seedy;

	stk1.push(p1);
	while(!stk1.isEmpty())
    {
        int next[4][2]={{0,-1},{1,0},{0,1},{-1,0}};
        p1=stk1.gettop();
        stk1.pop();

        glColor3f(1,0,0);
        glBegin(GL_POINTS);
            glVertex2i(p1.x,p1.y);
        glEnd();

        for(int i=0;i<4;i++)
        {
            int tx=p1.x+next[i][0];
            int ty=p1.y+next[i][1];
            glReadPixels(tx,ty,1,1,GL_RGBA,GL_UNSIGNED_BYTE,params);
            long c1=RGB(params[0],params[1],params[2]);
            if(c1==color||c1==boundary_color)
                continue;
            dcpt p2;
            p2.x=tx;
            p2.y=ty;
            stk1.push(p2);
        }
    }
}

MyStack.h(类声明文件)如下:

// MyStack.h: interface for the MyStack class.
#if !defined(AFX_MySTACK_H__3657DC2D_E518_4E5E_9A32_023B2A260ED7__INCLUDED_)
#define AFX_MySTACK_H__3657DC2D_E518_4E5E_9A32_023B2A260ED7__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <windows.h>
#include <GL/glut.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>

struct dcpt
{
	int x;
	int y;
};

struct pointStruct
{
	dcpt point;
	pointStruct * pNext;
};

class CMyStack
{
public:
    CMyStack();
    virtual ~CMyStack();
    BOOL pop();
    void push(dcpt pt);
    void empty();
    dcpt gettop();
    BOOL isEmpty();
private:
    pointStruct *pHead;
    pointStruct *p1;
    pointStruct *pTop;

};
#endif // !defined(AFX_MySTACK_H__3657DC2D_E518_4E5E_9A32_023B2A260ED7__INCLUDED_)

MyStack.cpp(类实现文件)如下:

// MyStack.cpp: implementation of the MyStack class.
#include "MyStack.h"
CMyStack::CMyStack()
{

    pHead=new pointStruct;
    p1=pTop=pHead;
    pHead->pNext=NULL;
}
CMyStack::~CMyStack()
{
    while(pTop!=NULL)
    {
        p1=pTop;
        pTop=pTop->pNext;
        delete p1;
    }
}

BOOL CMyStack::pop()
{
    if(pTop==pHead)
        return 0;
    p1=pTop;
    pTop=pTop->pNext;
    delete p1;
    return 1;
}

void CMyStack::push(dcpt pt)
{
    p1=new pointStruct;
    p1->point=pt;
    p1->pNext=pTop;
    pTop=p1;
}

void CMyStack::empty()
{
    while(pTop!=NULL)
    {
        p1=pTop;
        pTop=pTop->pNext;
        delete p1;
    }

}

dcpt CMyStack::gettop()
{
    return pTop->point;
}

BOOL CMyStack::isEmpty()
{

    if(pTop==pHead)
        return 1;
    return 0;
}

main.cpp(类使用)如下:

// ====== Computer Graphics Experiment #3 ======
// |          Boundary-Fill Algorithm          |
// =============================================
//
// Requirement:
//	Implement Boundary-Fill algorithm to fill polygon.


#include "MyStack.h"
#define WINDOW_HEIGHT 400

void Boundaryfill (int seedx,int seedy)
{
	CMyStack stk1;
    long color=RGB(255,0,0); //填充颜色 red
	long boundary_color=RGB(255,255,255); //边界颜色 white
	unsigned char params[4]; //保存读取的一个像素点的颜色值
	dcpt p1;
    p1.x=seedx;
	p1.y=seedy;

	stk1.push(p1);
	while(!stk1.isEmpty())
    {
        int next[4][2]={{0,-1},{1,0},{0,1},{-1,0}};
        p1=stk1.gettop();
        stk1.pop();

        glColor3f(1,0,0);
        glBegin(GL_POINTS);
            glVertex2i(p1.x,p1.y);
        glEnd();

        for(int i=0;i<4;i++)
        {
            int tx=p1.x+next[i][0];
            int ty=p1.y+next[i][1];
            glReadPixels(tx,ty,1,1,GL_RGBA,GL_UNSIGNED_BYTE,params);
            long c1=RGB(params[0],params[1],params[2]);
            if(c1==color||c1==boundary_color)
                continue;
            dcpt p2;
            p2.x=tx;
            p2.y=ty;
            stk1.push(p2);
        }
    }
}

void MyPolygonFill(int n, dcpt *vertices)
// n --- Number of vertices
// vertices --- vertex coordinates
{
	int max=vertices[0].x;
	int mix=vertices[0].x;
	int may=vertices[0].y;
	int miy=vertices[0].y;
	glColor3f(1.0, 1.0, 1.0);
	glBegin (GL_LINE_LOOP);
	for (int i=0;i<n;i++)
	{
		glVertex2i(vertices[i].x,vertices[i].y);
		if (vertices[i].x>max)
			max=vertices[i].x;
		if (vertices[i].x<mix)
			mix=vertices[i].x;
		if (vertices[i].y>may)
			may=vertices[i].y;
		if (vertices[i].y<miy)
			miy=vertices[i].y;
	}
    glEnd();
    int sx=(max+mix)/2;
	int sy=(may+miy)/2;
	Boundaryfill(sx,sy);

}

// Initialization function
void init(void)
{
	glClearColor (0.0, 0.0, 0.0, 0.0);
    glPixelStorei(GL_PACK_ALIGNMENT, 1);
}

// Display callback function
void display(void)
{
	static dcpt v[4];
	v[0].x = 260, v[0].y = 150;
	v[1].x = 281, v[1].y = 200;
	v[2].x = 340, v[2].y = 230;
	v[3].x = 370, v[3].y = 150;

	glClear(GL_COLOR_BUFFER_BIT);

	MyPolygonFill(4, v);

	glFlush();
}

// Reshape callback function
void reshape(int w, int h)
{
	glViewport (0, 0, w, h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(0, w, 0, h);
}

// Keyboard callback function
void keyboard(unsigned char key, int x, int y)
{
	switch (key) {
		case 27: exit(0);
	}
}

// Main program entrance
int main(int argc, char* argv[])
{
	glutInit(&argc, argv);
	glutInitDisplayMode (GLUT_RGB);
	glutInitWindowSize (650, 400);
	glutInitWindowPosition (50, 100);
	glutCreateWindow ("Polygon Fill");
	init ();
	glutDisplayFunc(display);
	glutReshapeFunc(reshape);
	glutKeyboardFunc(keyboard);
	glutMainLoop();
	return 0;
}

原文地址:https://www.cnblogs.com/vivid-victory/p/10090463.html