区域填充之扫描线算法

本文介绍了扫描线类算法在区域填充中的应用,特别是有序边表的扫描线算法。首先,解释了算法的基本思想,包括建立ET表、初始化AET表,并通过循环扫描线yi值来填充区域。在细节处理上,提到了顶点坐标存储、EdgeTable类的设计以及处理扫描线与顶点相交的问题。最后,作者分享了在实现过程中遇到的挑战和调试经验,强调了调bug的重要性。
摘要由CSDN通过智能技术生成

        区域的填充可以根据区域的填充,采用不同的填充算法,而其中有扫描线类算法和种子填充算法。这里,先介绍扫描线类算法之有序边表的扫描线算法。其他什么种子填充、边界标志算法、4连通区域的递归算法、8连通区域的递归算法、扫描线种子填充算法比较简单。

        其实有序边表其实领会了也好理解,关键是将思想转化为代码。

        先介绍算法思想:

        1.根据给出的多边形顶点坐标,建立ET表(同时计算ymax和ymin)

        2.初始化AET表,使之为空

        3.使用扫描线yi值作为循环变量,使之初始值为ymin

               重复做以下操作:

                  (1)如果ET表中yi桶非空,则合并到AET中

                  (2)对AET表中记录按x值从小到大排序

                  (3)依次取出表中记录,两两配对填充

                  (4)如果AET表中某记录的ymax=yi,则删除该记录

                  (5)对仍在AET中的记录,修改x值,x=x+1/m (m为斜率)

       现在,关键要细节的处理与代码实现。

       1.顶点坐标,由于无法确定顶点数,所以我们用一个数组保存。创建一个填充函数

          void regionfill(HDC hdc,Point1 *p,int len,int ymin,int ymax)  

          我们需要创建EdgeTable类,通过分析,这个结构很像我们数据结构的图(邻接表表示)

          代码如下:

/*
 *author qyl
 *date 2012/4/7
 *purpose 边表结构
 *version 1.1
 */

#include"LList.h"
#include"Point1.h"

class Edge{
public:
	float x;
	float increment;
	float ymax;

	Edge(){x=-1;increment=0;ymax=-1;}
	Edge(float x0,float incr,float y0)
	{
		x=x0;
		increment=incr;
		ymax=y0;
	}

	friend bool operator<(Edge &a,Link<Edge> &b)
	{
		return a.x<b.element.x;
	}

	friend bool operator>(Edge &a,Edge &b)
	{
		return a.x>b.x;
	}
};


class EdgeTable
{
private:
	int numberLine;
	int numberEdge;
	LList<Edge> **vertex;
public:
	EdgeTable(int numLine)
	{
		int i;
		numberLine=numLine;
		numberEdge=0;
		vertex=(LList<Edge>**) new LList<Edge>*[numberLine];
		for(i=0;i<numberLine;i++)
			vertex[i]=new LList<Edge>();
	}

	~EdgeTable()
	{
		for(int i=0;i<numberLine;i++)
			delete [] vertex[i];
		delete [] vertex;
	}

	int numberLines(){return numberLine;}
	int numberEdges(){return numberEdge;}

	bool isEmptyInLine(int pos)
	{
		return vertex[pos]->isEmpty();
	}

	LList<Edge>* getValue(int pos)
	{
		Edge it;
		LList<Edge>* l=new LList<Edge>();
		for(vertex[pos]->setStart();vertex[pos]->getValue(it);vertex[pos]->next())
		{
			l->insert(it);
		}
		return l;
	}



	void setEdge(int pos,Edge e)
	{
		Edge curr;
		for(vertex[pos]->setStart();vertex[pos]->getValue(curr);vertex[pos]->next())
		{
			if(curr.x<=e.x)
				break;
		}
		numberEdge++;
		vertex[pos]->insert(e);
	}

	void delEdge(int pos,Edge e)
	{
		Edge curr;
		for(vertex[pos]->setStart();vertex[pos]->getValue(curr);vertex[pos]->next())
		{
			if(curr.ymax==e.ymax)
			{
				vertex[pos]->remove(curr);
				numberEdge--;
			}
		}
	}

	void deleteAll(int pos)
	{
		numberEdge-=vertex[pos]->removeAll();
	}

	void createTableEdge(Point1 * p,int len,int ymin,int ymax)
	{
		Edge* e;

		/*version 1.2
		 *改进版本
		 */
		//计算各个顶点是否为奇异点,对每个顶点进行标记
		/*
		int *flag=new int[len];
	    for(int i=0;i<len;i++)
		{
			if(i==0)
			{
				if(p[1].getY()>p[0].getY() && p[len-1].getY()>p[0].getY())
					*(flag+i)=2;
				else if(p[1].getY()<p[0].getY() && p[len-1].getY()<p[0].getY())
					*(flag+i)=0;
				else if(p[1].getY()<p[0].getY() && p[len-1].getY()>p[0].getY())
					*(flag+i)=1;
				else if(p[(i+1)%len].getY()>p[i].getY() && p[len-1].getY()<p[i].getY())
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值