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; } }