typedef struct _IVT_TEDGE
{
float x;
float dx;
int ymax;
struct _IVT_TEDGE* Next;
}IVT_EDGE;
/************************************************************************/
/* 函数名:CreateROIImage
说明: 重建图像感兴趣区域
输入: polygon - 多边形顶点
nPolygonNUM—多边形顶点个数
nWidth—图像宽度
nHeight—图像高度
输出: 无
返回: 创建的图像感兴趣区域
/************************************************************************/
bool CreateROIImage(unsigned char *pImageROI,IVT_POINT* polygon, int nWidth, int nHeight, int nPolygonNUM)
{
if (pImageROI == NULL)
{
return false;
}
memset(pImageROI, 0, nWidth * nHeight*sizeof(unsigned char));
memset(pVIBESamples,0, nWidth*nHeight*sizeof(unsigned char));
ScanFill(polygon, nPolygonNUM, pImageROI, nWidth,nHeight);
return true;
}
/************************************************************************/
/* 函数名:ScanFill
说明:多边形填充的主体程序
输入:plolygonNum—多边形顶点个数
polygon—指向多边形顶点的指针数组
输出:pImage—感兴趣区域图像数据*/
/************************************************************************/
void ScanFill(IVT_POINT* polygon, int polygonNum, unsigned char *pImage, int nWidth, int nHeight)
{
IVT_EDGE **edges,*active;
int i,scan,scanmax = 0, scanmin = nHeight;
//计算所有多边形顶点坐标中y的最大值和最小值,以此作为扫描线的处理范围
for (i = 0; i < polygonNum/* - 1*/; i++)
{
if (scanmax < polygon[i].y)
{
scanmax = polygon[i].y;
}
if (scanmin > polygon[i].y)
{
scanmin = polygon[i].y;
}
}
//初始化每条扫描线的边链表
edges = (IVT_EDGE**)malloc(sizeof(IVT_EDGE*)*(scanmax - scanmin + 1));
for (scan = scanmin; scan <= scanmax; scan++)
{
edges[scan - scanmin] = NULL;
}
BuildEdgeList(polygonNum, polygon, edges, scanmin); //建立有序边表
active = NULL;
for (scan = scanmin; scan <= scanmax; scan++) //扫描每条扫描线,求活性表
{
BuildActiveList((scan - scanmin), active, edges); //建立活性边表
if (active)
{
FillScan(scan,active,pImage,nWidth); //填充当前扫描线
UpdateActiveList(scan,active); //更新活化边表
ResortActiveList(active); //重排活化边表
}
}
free((void*)edges);
}
/************************************************************************/
/* 函数名:BuildEdgeList
说明: 创建边表的主体函数
输入: cnt—多边形顶点个数
pts—多边形顶点坐标
输出: edges[]—指向活性边结点的指针数组
返回: 无*/
/************************************************************************/
void BuildEdgeList(int cnt, IVT_POINT* pts, IVT_EDGE* edges[],int yMin)
{
IVT_EDGE* edge;
IVT_POINT ps,pe,pss,pee;
int i;
edge = (IVT_EDGE*)malloc(sizeof(IVT_EDGE));
if (edge == NULL)
{
printf("edge malloc failed!\r\n");
return;
}
for (i = 0; i < cnt; i++)
{
ps = pts[i]; //当前处理边的起点
pe = pts[(i+1) % cnt]; //当前处理边的终点
pss = pts[(i-1+cnt) % cnt]; //起点的前一个相邻点
pee = pts[(i+2) % cnt]; //终点的后一个相邻点
if (ps.y != pe.y) //非水平线
{
edge->dx = (float)(pe.x - ps.x) / (float) (pe.y - ps.y);
if (pe.y > ps.y) //当前顶点不是奇点,建立边表时使用下一个顶点的y值即yNext
{
edge->x = ps.x;
if (pee.y >= pe.y)
{
edge->ymax = pe.y - 1;
}
else
{
edge->ymax = pe.y;
}
PushEdgeList(edges[ps.y - yMin],edge);
}
else
{
edge->x = pe.x;
if (pss.y >= ps.y)
{
edge->ymax = ps.y - 1;
}
else
{
edge->ymax = ps.y;
}
PushEdgeList(edges[pe.y - yMin],edge);
}
}
}
free(edge);
}
/************************************************************************/
/*函数名: BuildActiveList
说明:建立活性边表的主体函数,建立第scan条扫描线的活性边表
输入:scan—扫描线行数
edges—活性边列表
输出:active—活性边表
返回:无*/
/************************************************************************/
void BuildActiveList(int scan, IVT_EDGE* &active, IVT_EDGE* edges[])
{
IVT_EDGE *p,*q,*pA,*pA2;
if (edges[scan] == NULL)
{
return;
}
p = edges[scan]; //查找当前扫描线对应的y桶
q = p;
while(p)
{
q = p;
p = p->Next;
}
//对扫描线按照x值由小到大顺序添加
if (!active)
{
active = edges[scan];
}
else
{
//添加到表头
if (active->x > q->x)
{
q->Next = active;
active = edges[scan];
}
else
{
//添加表中间或结尾
pA = active;
pA2 = pA;
while(pA)
{
pA2 = pA;
pA = pA->Next;
if (pA)
{
if (pA->x > q->x)
{
break;
}
}
}
pA2->Next = edges[scan];
q->Next = pA;
}
}
}
/************************************************************************/
/*函数名:FillScan
说明: 填充一对交点的主体函数,填充扫描线上,且在下一结点到再下一结点之间的点
输入: scan—扫描线行数
active—活动边表
输出: pImage—感兴趣区域图像
返回: 无*/
/************************************************************************/
void FillScan(int scan, IVT_EDGE* active, unsigned char* pImage, int nWidth)
{
IVT_EDGE *p1,*p2;
int i;
p1 = active;
while (p1)
{
p2 = p1->Next;
for (i = p1->x; i < p2->x; i++)
{
pImage[scan * nWidth + i]= 255; //对图形内部的点置1
}
p1 = p2->Next; //活性表的下一条边表
}
}
/************************************************************************/
/* 函数名: UpdateActiveList
说明: 删除扫描线scan完成交点计算的活性边,同时更新交点x域
输入: scan—扫描线行数
输出: active—活动边表
返回: 无*/
/************************************************************************/
void UpdateActiveList(int scan, IVT_EDGE* &active)
{
IVT_EDGE *q = active;
IVT_EDGE *p = active;
IVT_EDGE *pDelete = active;
while(p)
{
if (scan >= p->ymax) //扫描线超过边的最大y值,此条件的节点应该删掉
{
//删除表头
if (active == p)
{
active = p->Next;
pDelete = p;
p = p->Next;
q = p;
free(pDelete);
}
else
{
//删除列表中间的结点
q->Next = p->Next;
pDelete = p;
p = p->Next;
free(pDelete);
}
}
else //扫描线未超过边的最大y值,相应的x值增加
{
p->x = p->x + p->dx;
q = p;
p = p->Next;
}
}
}
/************************************************************************/
/*函数名: ResortActiveList
说明: 对活性边表节点重新排序的主体函数,活性边表active中的节点按照x值从小到大重新排序
输入:
输出: active—活性边表
返回; 无*/
/************************************************************************/
void ResortActiveList(IVT_EDGE* &active)
{
IVT_EDGE *q;
IVT_EDGE *p = active;
IVT_EDGE *pMin;
IVT_EDGE *pChange;
int nMin;
pChange = (IVT_EDGE*)malloc(sizeof(IVT_EDGE));
while(p)
{
nMin = p->x;
pMin = p;
q = p;
while(q)
{
if (nMin > q->x)
{
pMin = q;
nMin = q->x;
}
q = q->Next;
}
if (pMin != p)
{
pChange->x = pMin->x;
pChange->dx = pMin->dx;
pChange->ymax = pMin->ymax;
pMin->x = p->x;
pMin->dx = p->dx;
pMin->ymax = p->ymax;
p->x = pChange->x;
p->dx = pChange->dx;
p->ymax = pChange->ymax;
}
p = p->Next;
}
free(pChange);
}
/************************************************************************/
/* 函数名:PushEdgeList
说明: 把新放入边列表中
输入: Edge—新边
输出: List—边列表
返回: 无*/
/************************************************************************/
void PushEdgeList(IVT_EDGE* &List, IVT_EDGE* Edge)
{
IVT_EDGE *p,*p2;
p = List;
p2 = List;
if (List)
{
while(p)
{
p2 = p;
p = p->Next;
}
p = (IVT_EDGE*)malloc(sizeof(IVT_EDGE));
p->x = Edge->x;
p->dx = Edge->dx;
p->ymax = Edge->ymax;
p->Next = NULL;
p2 ->Next = p;
}
else
{
List = (IVT_EDGE*)malloc(sizeof(IVT_EDGE));
List->x = Edge->x;
List->dx = Edge->dx;
List->ymax = Edge->ymax;
List->Next = NULL;
}
}