領域充填の走査線アルゴリズム

17547 ワード

領域の充填は、領域の充填に基づいて異なる充填アルゴリズムを採用することができ、その中には走査線クラスアルゴリズムとシード充填アルゴリズムがある.ここでは,まず走査線クラスアルゴリズムの秩序エッジテーブルの走査線アルゴリズムを紹介する.その他のシード充填、境界フラグアルゴリズム、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 &b)
	{
		return a.x(Edge &a,Edge &b)
	{
		return a.x>b.x;
	}
};


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

	~EdgeTable()
	{
		for(int i=0;iisEmpty();
	}

	LList* getValue(int pos)
	{
		Edge it;
		LList* l=new LList();
		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;ip[0].getY() && p[len-1].getY()>p[0].getY())
					*(flag+i)=2;
				else if(p[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() && p[(i-1)%len].getY()>p[i].getY()) *(flag+i)=2; else if(p[(i+1)%len].getY()

p[i].getY()) *(flag+i)=1; else if(p[(i+1)%len].getY()>p[i].getY() && p[(i-1)%len].getY()

insert(*e); } else { e=new Edge(p[j].getX(),(p[len-1].getX()-p[j].getX())/(p[len-1].getY()-p[j].getY()),p[len-1].getY()-1); vertex[i]->insert(*e); } break; case 2: if((*(flag+len-1))!=1 && (*(flag+len-1))!=3) { e=new Edge(p[j].getX(),(p[len-1].getX()-p[j].getX())/(p[len-1].getY()-p[j].getY()),p[len-1].getY()); vertex[i]->insert(*e); } else { e=new Edge(p[j].getX(),(p[len-1].getX()-p[j].getX())/(p[len-1].getY()-p[j].getY()),p[len-1].getY()-1); vertex[i]->insert(*e); } if((*(flag+j+1))!=1 && (*(flag+j+1)!=1)!=3) { e=new Edge(p[j].getX(),(p[(j+1)%len].getX()-p[j].getX())/(p[(j+1)%len].getY()-p[j].getY()),p[(j+1)%len].getY()); vertex[i]->insert(*e); } else { e=new Edge(p[j].getX(),(p[(j+1)%len].getX()-p[j].getX())/(p[(j+1)%len].getY()-p[j].getY()),p[(j+1)%len].getY()); vertex[i]->insert(*e); } break; case 3: if((*(flag+j+1))!=1 && (*(flag+j+1))!=3) { e=new Edge(p[j].getX(),(p[(j+1)%len].getX()-p[j].getX())/(p[(j+1)%len].getY()-p[j].getY()),p[(j+1)%len].getY()); vertex[i]->insert(*e); } else { e=new Edge(p[j].getX(),(p[(j+1)%len].getX()-p[j].getX())/(p[(j+1)%len].getY()-p[j].getY()),p[(j+1)%len].getY()-1); vertex[i]->insert(*e); } break; default: break; } } else { switch(mark) { case 0: break; case 1: if((*(flag+j-1))!=1 && (*(flag+j-1))!=3) { e=new Edge(p[j].getX(),(p[len-1].getX()-p[j].getX())/(p[len-1].getY()-p[j].getY()),p[j-1].getY()); vertex[i]->insert(*e); } else { e=new Edge(p[j].getX(),(p[len-1].getX()-p[j].getX())/(p[len-1].getY()-p[j].getY()),p[j-1].getY()-1); vertex[i]->insert(*e); } break; case 2: if((*(flag+(j+1)%len))!=1 && (*(flag+(j+1)%len))!=3) { e=new Edge(p[j].getX(),(p[(j+1)%len].getX()-p[j].getX())/(p[(j+1)%len].getY()-p[j].getY()),p[(j+1)%len].getY()); vertex[i]->insert(*e); } else { e=new Edge(p[j].getX(),(p[(j+1)%len].getX()-p[j].getX())/(p[(j+1)%len].getY()-p[j].getY()),p[(j+1)%len].getY()-1); vertex[i]->insert(*e); } if((*(flag+j-1))!=1 && (*(flag+j-1))!=3) { e=new Edge(p[j].getX(),(p[len-1].getX()-p[j].getX())/(p[len-1].getY()-p[j].getY()),p[j-1].getY()); vertex[i]->insert(*e); } else { e=new Edge(p[j].getX(),(p[len-1].getX()-p[j].getX())/(p[len-1].getY()-p[j].getY()),p[j-1].getY()-1); vertex[i]->insert(*e); } break; case 3: if((*(flag+(j+1)%len))!=1 && (*(flag+(j+1)%len))!=3) { e=new Edge(p[j].getX(),(p[(j+1)%len].getX()-p[j].getX())/(p[(j+1)%len].getY()-p[j].getY()),p[(j+1)%len].getY()); vertex[i]->insert(*e); } else { e=new Edge(p[j].getX(),(p[(j+1)%len].getX()-p[j].getX())/(p[(j+1)%len].getY()-p[j].getY()),p[(j+1)%len].getY()-1); vertex[i]->insert(*e); } break; default: break; } } } } } */ /* for(int i=ymin;i<=ymax;i++) { for(int j=0;jp[0].getY() && p[len-1].getY()>p[0].getY()) { e=new Edge(p[j].getX(),(p[(j+1)%len].getX()-p[j].getX())/(p[(j+1)%len].getY()-p[j].getY()),p[(j+1)%len].getY()-1); vertex[i]->insert(*e); e=new Edge(p[j].getX(),(p[len-1].getX()-p[j].getX())/(p[len-1].getY()-p[j].getY()),p[len-1].getY()-1); vertex[i]->insert(*e); } // ymax-1 else if(p[1].getY()>p[0].getY() && p[len-1].getY()

insert(*e); } // ymax-1 else if(p[1].getY()

p[0].getY()) { e=new Edge(p[j].getX(),(p[len-1].getX()-p[j].getX())/(p[len-1].getY()-p[j].getY()),p[len-1].getY()-1); vertex[i]->insert(*e); } } else { if(p[(j+1)%len].getY()>p[j].getY() && p[(j-1)%len].getY()>p[j].getY()) { e=new Edge(p[j].getX(),(p[(j+1)%len].getX()-p[j].getX())/(p[(j+1)%len].getY()-p[j].getY()),p[(j+1)%len].getY()-1); vertex[i]->insert(*e); e=new Edge(p[j].getX(),(p[(j-1)%len].getX()-p[j].getX())/(p[(j-1)%len].getY()-p[j].getY()),p[(j-1)%len].getY()-1); vertex[i]->insert(*e); } // ymax-1 else if(p[(j+1)%len].getY()>p[j].getY() && p[(j-1)%len].getY()

insert(*e); } // ymax-1 else if(p[(j+1)%len].getY()

p[j].getY()) { e=new Edge(p[j].getX(),(p[(j-1)%len].getX()-p[j].getX())/(p[(j-1)%len].getY()-p[j].getY()),p[(j-1)%len].getY()-1); vertex[i]->insert(*e); } } } } */ /* for(int j=0;jp[0].getY() && p[len-1].getY()>p[0].getY()) { e=new Edge(p[j].getX(),(p[(j+1)%len].getX()-p[j].getX())/(p[(j+1)%len].getY()-p[j].getY()),p[(j+1)%len].getY()-1); vertex[i]->insert(*e); e=new Edge(p[j].getX(),(p[len-1].getX()-p[j].getX())/(p[len-1].getY()-p[j].getY()),p[len-1].getY()-1); vertex[i]->insert(*e); } // ymax-1 else if(p[1].getY()>p[0].getY() && p[len-1].getY()

insert(*e); } // ymax-1 else if(p[1].getY()

p[0].getY()) { e=new Edge(p[1].getX(),(p[1].getX()-p[j].getX())/(p[1].getY()-p[j].getY()),p[1].getY()-1); vertex[(int)p[1].getY()]->insert(*e); } } else { if(p[(j+1)%len].getY()>p[j].getY() && p[(j-1)%len].getY()>p[j].getY()) { e=new Edge(p[j].getX(),(p[(j+1)%len].getX()-p[j].getX())/(p[(j+1)%len].getY()-p[j].getY()),p[(j+1)%len].getY()-1); vertex[i]->insert(*e); e=new Edge(p[j].getX(),(p[(j-1)%len].getX()-p[j].getX())/(p[(j-1)%len].getY()-p[j].getY()),p[(j-1)%len].getY()-1); vertex[i]->insert(*e); } // ymax-1 else if(p[(j+1)%len].getY()>p[j].getY() && p[(j-1)%len].getY()

insert(*e); } // ymax-1 else if(p[(j+1)%len].getY()

p[j].getY()) { e=new Edge(p[(j+1)%len].getX(),(p[(j+1)%len].getX()-p[j].getX())/(p[(j+1)%len].getY()-p[j].getY()),p[(j+1)%len].getY()-1); vertex[(int)p[(j+1)%len].getX()]->insert(*e); } } } */ for(int i=ymin;i<=ymax;i++) { for(int j=0;jp[0].getY() && p[len-1].getY()>p[0].getY()) { if(p[2].getY()>p[1].getY()) { e=new Edge(p[j].getX(),(p[(j+1)%len].getX()-p[j].getX())/(p[(j+1)%len].getY()-p[j].getY()),p[(j+1)%len].getY()-1); vertex[i]->insert(*e); } else { e=new Edge(p[j].getX(),(p[(j+1)%len].getX()-p[j].getX())/(p[(j+1)%len].getY()-p[j].getY()),p[(j+1)%len].getY()); vertex[i]->insert(*e); } if(p[len-2].getY()>p[len-1].getY()) { e=new Edge(p[j].getX(),(p[len-1].getX()-p[j].getX())/(p[len-1].getY()-p[j].getY()),p[len-1].getY()-1); vertex[i]->insert(*e); } else { e=new Edge(p[j].getX(),(p[len-1].getX()-p[j].getX())/(p[len-1].getY()-p[j].getY()),p[len-1].getY()); vertex[i]->insert(*e); } } // ymax-1 else if(p[1].getY()>p[0].getY() && p[len-1].getY()

p[1].getY()) { e=new Edge(p[j].getX(),(p[(j+1)%len].getX()-p[j].getX())/(p[(j+1)%len].getY()-p[j].getY()),p[(j+1)%len].getY()-1); vertex[i]->insert(*e); } else { e=new Edge(p[j].getX(),(p[(j+1)%len].getX()-p[j].getX())/(p[(j+1)%len].getY()-p[j].getY()),p[(j+1)%len].getY()); vertex[i]->insert(*e); } } // ymax-1 else if(p[1].getY()

p[0].getY()) { if(p[len-2].getY()>p[len-1].getY()) { e=new Edge(p[j].getX(),(p[len-1].getX()-p[j].getX())/(p[len-1].getY()-p[j].getY()),p[len-1].getY()-1); vertex[i]->insert(*e); } else { e=new Edge(p[j].getX(),(p[len-1].getX()-p[j].getX())/(p[len-1].getY()-p[j].getY()),p[len-1].getY()); vertex[i]->insert(*e); } } } else { if(p[(j+1)%len].getY()>p[j].getY() && p[j-1].getY()>p[j].getY()) { if(p[(j+2)%len].getY()>p[(j+1)%len].getY()) { e=new Edge(p[j].getX(),(p[(j+1)%len].getX()-p[j].getX())/(p[(j+1)%len].getY()-p[j].getY()),p[(j+1)%len].getY()-1); vertex[i]->insert(*e); } else { e=new Edge(p[j].getX(),(p[(j+1)%len].getX()-p[j].getX())/(p[(j+1)%len].getY()-p[j].getY()),p[(j+1)%len].getY()); vertex[i]->insert(*e); } if(j==1) { if(p[len-1].getY()>p[j-1].getY()) { e=new Edge(p[j].getX(),(p[(j-1)%len].getX()-p[j].getX())/(p[(j-1)%len].getY()-p[j].getY()),p[(j-1)%len].getY()-1); vertex[i]->insert(*e); } else { e=new Edge(p[j].getX(),(p[(j-1)%len].getX()-p[j].getX())/(p[(j-1)%len].getY()-p[j].getY()),p[(j-1)%len].getY()); vertex[i]->insert(*e); } } else { if(p[j-2].getY()>p[j-1].getY()) { e=new Edge(p[j].getX(),(p[(j-1)%len].getX()-p[j].getX())/(p[(j-1)%len].getY()-p[j].getY()),p[(j-1)%len].getY()-1); vertex[i]->insert(*e); } else { e=new Edge(p[j].getX(),(p[(j-1)%len].getX()-p[j].getX())/(p[(j-1)%len].getY()-p[j].getY()),p[(j-1)%len].getY()); vertex[i]->insert(*e); } } } // ymax-1 else if(p[(j+1)%len].getY()>p[j].getY() && p[(j-1)%len].getY()

p[(j+1)%len].getY()) { e=new Edge(p[j].getX(),(p[(j+1)%len].getX()-p[j].getX())/(p[(j+1)%len].getY()-p[j].getY()),p[(j+1)%len].getY()-1); vertex[i]->insert(*e); } else { e=new Edge(p[j].getX(),(p[(j+1)%len].getX()-p[j].getX())/(p[(j+1)%len].getY()-p[j].getY()),p[(j+1)%len].getY()); vertex[i]->insert(*e); } } // ymax-1 else if(p[(j+1)%len].getY()

p[j].getY()) { if(j==1) { if(p[len-1].getY()>p[j-1].getY()) { e=new Edge(p[j].getX(),(p[(j-1)%len].getX()-p[j].getX())/(p[(j-1)%len].getY()-p[j].getY()),p[(j-1)%len].getY()-1); vertex[i]->insert(*e); } else { e=new Edge(p[j].getX(),(p[(j-1)%len].getX()-p[j].getX())/(p[(j-1)%len].getY()-p[j].getY()),p[(j-1)%len].getY()); vertex[i]->insert(*e); } } else { if(p[j-2].getY()>p[j-1].getY()) { e=new Edge(p[j].getX(),(p[(j-1)%len].getX()-p[j].getX())/(p[(j-1)%len].getY()-p[j].getY()),p[(j-1)%len].getY()-1); vertex[i]->insert(*e); } else { e=new Edge(p[j].getX(),(p[(j-1)%len].getX()-p[j].getX())/(p[(j-1)%len].getY()-p[j].getY()),p[(j-1)%len].getY()); vertex[i]->insert(*e); } } } } } } } };


コードは少し乱れていますが、いくつかの間違いの私は削除していません.ただ、どのように一歩一歩改善したのか、発見した間違いを示しています.変更した後、いくつかの注釈も修正したようです.
この時計は構造が成り立っていれば,実はほかの時計は簡単だ.
この関数は走査線アルゴリズムです.
void regionfill(HDC hdc,Point1 *p,int len,int ymin,int ymax)
{
	EdgeTable ET(/*ymax-ymin+1*/1024);
	//  ET 
	ET.createTableEdge(p,len,ymin,ymax);
	//   AET 
	EdgeTable AET(1024);
	LList* l,*ptr;
	for(int i=ymin;i<=ymax;i++)
	{
	//  ET  i   ,           AET  
	    if(!ET.isEmptyInLine(i))
		{
			Edge curr;
			l=ET.getValue(i);
			for(l->setStart();l->getValue(curr);l->next())
			{
			    AET.setEdge(i,curr);
			}
			l->removeAll();
		}
	// AET         
		Edge curr;
		Edge temp;
		Edge min;
		
		ptr=l=AET.getValue(i);
		/*
		AET.deleteAll(i);
		int count=0;
		for(l->setStart();l->getValue(curr);l->next())
		{
			min=curr;
			for(ptr->setPos(count);ptr->getValue(curr);ptr->next())
			{
				if(min.x>curr.x)
					min=curr;
			}
			count++;
			AET.setEdge(i,min);
		}
		*/

	//    AET     y    ,      
		
		
		for(l->setStart();l->getValue(curr);l->next())
		{
			l->next();
			l->getValue(temp);
			for(int x0=int(curr.x);x0<=temp.x;x0++)
				SetPixel(hdc,x0,i,255);
	//  AET      ymax=   y,      
			if(curr.ymax==i)
				AET.delEdge(i,curr);
			if(temp.ymax==i)
				AET.delEdge(i,temp);
			}
	// AET         x    
		    ptr->removeAll();
			ptr=AET.getValue(i);
			for(ptr->setStart();ptr->getValue(curr);ptr->next())
			{
				curr.x+=curr.increment;
				AET.setEdge(i+1,curr);
			}
			//       AET      l,ptr
			AET.deleteAll(i);
			l->removeAll();
			ptr->removeAll();
		}
}

最後に、細部の問題について話します.スキャンラインが頂点と交差する場合、交点個数の計算を正しく行わなければなりません.そうしないとエラーが発生します.これは私はすでにEdgeTableクラスに含まれていて、上に2つの考え方を示しましたが、そのうちの1つは時間の問題ですべて完成したので、注釈されて、修正することに興味があります.ハ、コード共有ハ.頂点の前後にリングが接続されているため、私が使っている配列は、いくつかの特殊な状況に注意してください.もちろん、ループチェーンテーブルも使えます.
最大最小値を求める場合は、関数解を作成することもできます.ここでは、簡単にするために手動入力を採用します.針もあるので気をつけてください.ソートすると言ったかもしれませんが、ソートしていません.それは私がレコードを挿入してソートして挿入したものです.
カッコ1つで100以上のエラーが増え、1つの変数が午前1時まで振り回されたため・・・
最后の最后に、私はただ言いたいだけで、デバッグは根気と忍耐力を试す仕事です!!!
添付:コードのダウンロード:http://download.csdn.net/my