opencv FillEdgeCollection
static void FillEdgeCollection( Mat& img, std::vector<PolyEdge>& edges, const void* color ) { PolyEdge tmp; int i, y, total = (int)edges.size(); Size size = img.size(); PolyEdge* e; int y_max = INT_MIN, y_min = INT_MAX; int64 x_max = 0xFFFFFFFFFFFFFFFF, x_min = 0x7FFFFFFFFFFFFFFF; int pix_size = (int)img.elemSize(); if( total < 2 ) return; for( i = 0; i < total; i++ ) { PolyEdge& e1 = edges[i]; assert( e1.y0 < e1.y1 ); // Determine x-coordinate of the end of the edge. // (This is not necessary x-coordinate of any vertex in the array.) int64 x1 = e1.x + (e1.y1 - e1.y0) * e1.dx; y_min = std::min( y_min, e1.y0 ); y_max = std::max( y_max, e1.y1 ); x_min = std::min( x_min, e1.x ); x_max = std::max( x_max, e1.x ); x_min = std::min( x_min, x1 ); x_max = std::max( x_max, x1 ); } if( y_max < 0 || y_min >= size.height || x_max < 0 || x_min >= ((int64)size.width<<XY_SHIFT) ) return; std::sort( edges.begin(), edges.end(), CmpEdges() ); // start drawing tmp.y0 = INT_MAX; edges.push_back(tmp); // after this point we do not add // any elements to edges, thus we can use pointers i = 0; tmp.next = 0; e = &edges[i]; y_max = MIN( y_max, size.height ); for( y = e->y0; y < y_max; y++ ) { PolyEdge *last, *prelast, *keep_prelast; int sort_flag = 0; int draw = 0; int clipline = y < 0; prelast = &tmp; last = tmp.next; while( last || e->y0 == y ) { if( last && last->y1 == y ) { // exclude edge if y reaches its lower point prelast->next = last->next; last = last->next; continue; } keep_prelast = prelast; if( last && (e->y0 > y || last->x < e->x) ) { // go to the next edge in active list prelast = last; last = last->next; } else if( i < total ) { // insert new edge into active list if y reaches its upper point prelast->next = e; e->next = last; prelast = e; e = &edges[++i]; } else break; if( draw ) { if( !clipline ) { // convert x's from fixed-point to image coordinates uchar *timg = img.ptr(y); int x1, x2; if (keep_prelast->x > prelast->x) { x1 = (int)((prelast->x + XY_ONE - 1) >> XY_SHIFT); x2 = (int)(keep_prelast->x >> XY_SHIFT); } else { x1 = (int)((keep_prelast->x + XY_ONE - 1) >> XY_SHIFT); x2 = (int)(prelast->x >> XY_SHIFT); } // clip and draw the line if( x1 < size.width && x2 >= 0 ) { if( x1 < 0 ) x1 = 0; if( x2 >= size.width ) x2 = size.width - 1; ICV_HLINE( timg, x1, x2, color, pix_size ); } } keep_prelast->x += keep_prelast->dx; prelast->x += prelast->dx; } draw ^= 1; } // sort edges (using bubble sort) keep_prelast = 0; do { prelast = &tmp; last = tmp.next; while( last != keep_prelast && last->next != 0 ) { PolyEdge *te = last->next; // swap edges if( last->x > te->x ) { prelast->next = te; last->next = te->next; te->next = last; prelast = te; sort_flag = 1; } else { prelast = last; last = te; } } keep_prelast = prelast; } while( sort_flag && keep_prelast != tmp.next && keep_prelast != &tmp ); } }
代码来自:opencv-mastermodulesimgprocsrcdrawing.cpp
##########################################