高分求矢量图形的扫描线区域填充源程序!

allenhai1980 2003-10-21 11:41:54
谢谢各位大虾。
我在论坛中没有搜索到相关的合适源程序,又没时间自己写,
所以想要现成的,呵呵。
C++语言的。
allenhai@sina.com
...全文
106 点赞 收藏 15
写回复
15 条回复
tuxw 2003年12月25日
void LineFill( CDC *pDC, const CRect& rc, int nFillMode, int nDis )
{
CPen pen( PS_SOLID, 0, RGB(255,0,0) ); // 测试用的填充颜色
CPen *pOldPen = pDC->SelectObject( &pen );

const COLORREF crText = RGB(0,0,0); // 已画好的字体颜色
COLORREF cr1, cr2;

if( nFillMode == 0 ) { // 水平填充
for( int row = rc.top; row < rc.bottom; row += nDis ) {
cr1 = pDC->GetPixel( rc.left+1, row );
for( int col = rc.left+2; col < rc.right; ++col ) {
cr2 = pDC->GetPixel( col, row );

if( cr1 != cr2 ) {
if( cr2 == crText )
pDC->MoveTo( col, row );
else if( cr1 == crText )
pDC->LineTo( col, row );
cr1 = cr2;
}
}
}
}
……

pDC->SelectObject( pOldPen );
}
回复 点赞
allenhai1980 2003年10月27日
Thanks zzuw very much.
我自己写吧,虽然耗时间!呵呵。
回复 点赞
zzwu 2003年10月25日
详细的算法描述见:
http://www.cs.uct.ac.za/courses/CS300W/IG/2003/handouts/scanlineHandout.pdf
回复 点赞
zzwu 2003年10月25日
allenhai1980(心蓝世界) :
程序写起来确实很麻烦,要自己从头开始编确实需要许多时间和精力。我估计这里参与讨论的人中做过这样工作的人不一定有,除了我之外,我以前也是因LSI设计工作的需要才做的。
不过,到网上再搜索一下看,说不定会有。
回复 点赞
allenhai1980 2003年10月24日
呵呵,想不到,我所要的算法就是zzwu(未名)所说的“桶算法”!
zzwu(未名)给出的四步很粗糙。
算法思想不难,当同时对很多多边形填充时,程序写起来很麻烦。
所以我想请各位提供一些类似的程序,不情之请啊!
回复 点赞
allenhai1980 2003年10月24日
大家帮忙啦!
回复 点赞
zzwu 2003年10月24日
“桶算法”就是老老实实地对封闭多边形进行由上到下的水平线填充,为此要做的工作大体为:

1.先对多边形的边,按y投影的大小重新排序,设y范围为[ymin,ymax]
2.求水平线hl[y]和多边形的边的交,p[y,1],p[y,2],p[y,3]...,y属于[ymin,ymax]
3.对交点按x大小排序,q[y,1]<q[y,2]<q[y,3]<q[y,4]<....
4.则要填的扫描线就是,q[y,1]-q[y,2],q[y,3]-q[y,4],....

由于桶算法是从上到下依次填充的,所以用不到进出堆栈的操作;同时,因相邻水平线一般都是和多边形的同一些边求交,所以多边形边与y高度水平线的交点可利用与y-1的交点算出(类似bresenham算法),从而速度是快的。

麻烦的是:从上到下求水平线交点时,要控制多边形的边的改变,另外要考察各种特例交点。



回复 点赞
zzwu 2003年10月22日
以上算法从速度来看并不高,要考虑速度,应使用“桶算法”,但编写程序较繁了。
回复 点赞
alphapaopao 2003年10月22日
不错不错
回复 点赞
Freshyy 2003年10月22日
To zzwu(未名) :
“桶算法”的原理能大致介绍一下吗?谢谢!
回复 点赞
Freshyy 2003年10月22日
不是一个版块!
积分不一样的!
回复 点赞
allenhai1980 2003年10月22日
To alphapaopao(炮炮):
你不是有很多星的么,咋整的?
回复 点赞
allenhai1980 2003年10月22日
谢谢zzwu(未名)提供的程序。

我没有说清意图:我并不是想对任意区域填充,我的操作对象是多个多边形,填充也只是一种理解,我本想拿水平直线与所有的封闭多边形求交从而依次得到水平交点,从而将由边描述的矢量多边形转化成由很多水平直线构成的一个多边形区域,水平直线的密度当然不可能很大,种子填充是一种方式,但不好用水平直线的端点来表述。

另外,如果图形太大且很多,会不会发生递归的堆栈溢出?所以我想直接运算。效率很差,呵呵。如果能提供一些较好的直接拿水平直线填充多边形的算法程序,就太好了。

To yalinliu(亚林) :我知道有,谢谢提示。
回复 点赞
zzwu 2003年10月21日
我用pascal编过扫描线算法区域填充程序,但未用C++编过这样的程序。

以下是从网上找到的C++区域填充程序,注意,扫描线算法可以有多种类型,这里只是一种,是否适合你的,要检查:

 
区域填充的扫描线算法:

区域填充的递归算法原理和程序都很简单,但由于多次递归,费时、费内存,效率不高。为了减少递归次数,提高效率可以采用扫描线算法。算法的基本过程如下:当给定种子点(x,y)时,首先填充种子点所在扫描线上的位于给定区域的一个区段,然后确定与这一区段相连通的上、下两条扫描线上位于给定区域内的区段,并依次保存下来。反复这个过程,直到填充结束。

区域填充的扫描线算法可由下列四个步骤实现:

(1)初始化:堆栈置空。将种子点(x,y)入栈。

(2)出栈:若栈空则结束。否则取栈顶元素(x,y),以y作为当前扫描线。

(3)填充并确定种子点所在区段:从种子点(x,y)出发,沿当前扫描线向左、右两个方向填充,直到边界。分别标记区段的左、右端点坐标为xl和xr。

(4)并确定新的种子点:在区间[xl,xr]中检查与当前扫描线y上、下相邻的两条扫描线上的象素。若存在非边界、未填充的象素,则把每一区间的最右象素作为种子点压入堆栈,返回第(2)步。

区域填充的扫描线算法:

typedef struct{ //记录种子点

intx;

int y;

} Seed;

void ScanLineFill4(int x,int y,COLORREF oldcolor,COLORREF newcolor)

{ int xl,xr,i;

bool spanNeedFill;

Seed pt;

setstackempty();

pt.x =x; pt.y=y;

stackpush(pt); //将前面生成的区段压入堆栈

while(!isstackempty())

{ pt = stackpop();

y=pt.y;

x=pt.x;

while(getpixel(x,y)==oldcolor) //向右填充

{ drawpixel(x,y,newcolor);

x++;

}

xr = x-1;

x = pt.x-1;

while(getpixel(x,y)==oldcolor) //向左填充

{ drawpixel(x,y,newcolor);

x--;

}

xl = x+1;

//处理上面一条扫描线

x = xl;

y = y+1;

while(x<xr)

{ spanNeedFill=FALSE;

while(getpixel(x,y)==oldcolor)

{ spanNeedFill=TRUE;

x++;

}

if(spanNeedFill)

{ pt.x=x-1;pt.y=y;

stackpush(pt);

spanNeedFill=FALSE;

}

while(getpixel(x,y)!=oldcolor && x<xr) x++;

}//End of while(i<xr)

//处理下面一条扫描线,代码与处理上面一条扫描线类似

x = xl;

y = y-2;

while(x<xr)

{ ....

}//End of while(i<xr)

}//End of while(!isstackempty())

}
回复 点赞
yalinliu 2003年10月21日
计算机图形学上有类似的算法!
回复 点赞
发动态
发帖子
机器视觉
创建于2007-08-27

2575

社区成员

1.4w+

社区内容

图形图像/机器视觉
社区公告
暂无公告