cvdrawing.cpp.svn-base

来自「非结构化路识别」· SVN-BASE 代码 · 共 2,174 行 · 第 1/5 页

SVN-BASE
2,174
字号
static void
icvFillEdgeCollection( CvMat* img, CvContour* edges, const void* color )
{
    CvPolyEdge tmp;
    int i, y, total = edges->total;
    CvSeqReader reader;
    CvSize size = icvGetMatSize(img);
    CvPolyEdge* e;
    int y_max = INT_MIN;
    int pix_size = icvPixSize[CV_MAT_TYPE(img->type)];

    __BEGIN__;
    
    memset( &tmp, 0, sizeof(tmp));
    
    /* check parameters */
    if( edges->total < 2 || edges->rect.height < 0 || edges->rect.y >= size.height ||
        edges->rect.width < 0 || edges->rect.x >= size.width )
        EXIT;

    icvSortPolyEdges( (CvSeq*)edges, 0 );

    cvStartReadSeq( (CvSeq*)edges, &reader );

#ifdef _DEBUG
    e = &tmp;
    tmp.y0 = INT_MIN;
#endif

    for( i = 0; i < total; i++ )
    {
        CvPolyEdge* e1 = (CvPolyEdge*)(reader.ptr);

#ifdef _DEBUG
        assert( ICV_CMP_EDGES( *e, *e1 ) != 0 );
        e = e1;
#endif
        y_max = CV_MAX( y_max, e1->y1 );

        CV_NEXT_SEQ_ELEM( sizeof(CvPolyEdge), reader );
    }

    if( y_max >= size.height )
        y_max = size.height - 1;

    /* start drawing */
    tmp.y0 = INT_MAX;
    cvSeqPush( (CvSeq*)edges, &tmp );

    i = 0;
    tmp.next = 0;
    cvStartReadSeq( (CvSeq*)edges, &reader );
    e = (CvPolyEdge*)(reader.ptr);
    y = e->y0;

    do
    {
        CvPolyEdge *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 )
            {
                /* exlude edge if y reachs 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 reachs its upper point */
                prelast->next = e;
                e->next = last;
                prelast = e;
                CV_NEXT_SEQ_ELEM( edges->elem_size, reader );
                e = (CvPolyEdge*)(reader.ptr);
                i++;
            }
            else
                break;

            if( draw )
            {
                if( !clipline )
                {
                    /* convert x's from fixed-point to image coordinates */
                    uchar *timg = (uchar*)(img->data.ptr) + y * img->step;
                    int x1 = keep_prelast->x;
                    int x2 = prelast->x;

                    if( x1 > x2 )
                    {
                        int t = x1;

                        x1 = x2;
                        x2 = t;
                    }

                    x1 = (x1 + (1 << 15)) >> 16;
                    x2 = (x2 + (1 << 15)) >> 16;

                    /* 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 (bubble sort on list) */
        keep_prelast = 0;

        do
        {
            prelast = &tmp;
            last = tmp.next;

            while( last != keep_prelast && last->next != 0 )
            {
                CvPolyEdge *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 );
    }
    while( (++y) < y_max );

    __END__;
}


/* draws simple circle */
static void
icvCircle( CvMat* img, CvPoint center, int radius, const void* color )
{
    CvSize size = icvGetMatSize( img );
    int step = img->step;
    int pix_size = icvPixSize[CV_MAT_TYPE(img->type)];
    uchar* ptr = (uchar*)(img->data.ptr);
    int err = 0, dx = radius, dy = 0, plus = 1, minus = (radius << 1) - 1;
    int inside = center.x >= radius && center.x < size.width - radius &&
        center.y >= radius && center.y < size.height - radius;

    #define ICV_PUT_POINT( ptr, x )   \
        memcpy( (ptr) + (x)*pix_size, color, pix_size )

    while( dx >= dy )
    {
        int mask;
        int y11 = center.y - dy, y12 = center.y + dy, y21 = center.y - dx, y22 = center.y + dx;

        int x11 = center.x - dx, x12 = center.x + dx, x21 = center.x - dy, x22 = center.x + dy;

        if( inside )
        {
            uchar *tptr0 = ptr + y11 * step;
            uchar *tptr1 = ptr + y12 * step;

            ICV_PUT_POINT( tptr0, x11 );
            ICV_PUT_POINT( tptr1, x11 );
            ICV_PUT_POINT( tptr0, x12 );
            ICV_PUT_POINT( tptr1, x12 );

            tptr0 = ptr + y21 * step;
            tptr1 = ptr + y22 * step;

            ICV_PUT_POINT( tptr0, x21 );
            ICV_PUT_POINT( tptr1, x21 );
            ICV_PUT_POINT( tptr0, x22 );
            ICV_PUT_POINT( tptr1, x22 );
        }
        else if( x11 < size.width && x12 >= 0 && y21 < size.height && y22 >= 0 )
        {
            if( (unsigned) y11 < (unsigned) size.height )
            {
                uchar *tptr = ptr + y11 * step;

                if( x11 >= 0 )
                    ICV_PUT_POINT( tptr, x11 );
                if( x12 < size.width )
                    ICV_PUT_POINT( tptr, x12 );
            }

            if( (unsigned) y12 < (unsigned) size.height )
            {
                uchar *tptr = ptr + y12 * step;

                if( x11 >= 0 )
                    ICV_PUT_POINT( tptr, x11 );
                if( x12 < size.width )
                    ICV_PUT_POINT( tptr, x12 );
            }

            if( x21 < size.width && x22 >= 0 )
            {
                if( (unsigned) y21 < (unsigned) size.height )
                {
                    uchar *tptr = ptr + y21 * step;

                    if( x21 >= 0 )
                        ICV_PUT_POINT( tptr, x21 );
                    if( x22 < size.width )
                        ICV_PUT_POINT( tptr, x22 );
                }

                if( (unsigned) y22 < (unsigned) size.height )
                {
                    uchar *tptr = ptr + y22 * step;

                    if( x21 >= 0 )
                        ICV_PUT_POINT( tptr, x21 );
                    if( x22 < size.width )
                        ICV_PUT_POINT( tptr, x22 );
                }
            }
        }
        dy++;
        err += plus;
        plus += 2;

        mask = (err <= 0) - 1;

        err -= minus & mask;
        dx += mask;
        minus -= mask & 2;
    }

    #undef  ICV_PUT_POINT
}


/****************************************************************************************\
*                      Cicle drawing using direct Bresenham algorithm                    *
\****************************************************************************************/

/* draws filled circle */
static void
icvFillCircle( CvMat* img, CvPoint center, int radius, const void* color )
{
    CvSize size = icvGetMatSize( img );
    int step = img->step;
    int pix_size = icvPixSize[CV_MAT_TYPE(img->type)];
    uchar* ptr = (uchar*)(img->data.ptr);
    int err = 0, dx = radius, dy = 0, plus = 1, minus = (radius << 1) - 1;
    int inside = center.x >= radius && center.x < size.width - radius &&
        center.y >= radius && center.y < size.height - radius;

    while( dx >= dy )
    {
        int mask;
        int y11 = center.y - dy, y12 = center.y + dy, y21 = center.y - dx, y22 = center.y + dx;
        int x11 = center.x - dx, x12 = center.x + dx, x21 = center.x - dy, x22 = center.x + dy;

        if( inside )
        {
            uchar *tptr0 = ptr + y11 * step;
            uchar *tptr1 = ptr + y12 * step;

            ICV_HLINE( tptr0, x11, x12, color, pix_size );
            ICV_HLINE( tptr1, x11, x12, color, pix_size );

            tptr0 = ptr + y21 * step;
            tptr1 = ptr + y22 * step;

            ICV_HLINE( tptr0, x21, x22, color, pix_size );
            ICV_HLINE( tptr1, x21, x22, color, pix_size );
        }
        else if( x11 < size.width && x12 >= 0 && y21 < size.height && y22 >= 0 )
        {
            x11 = CV_MAX( x11, 0 );
            x12 = CV_MIN( x12, size.width - 1 );

            if( (unsigned) y11 < (unsigned) size.height )
            {
                uchar *tptr = ptr + y11 * step;
                ICV_HLINE( tptr, x11, x12, color, pix_size );
            }

            if( (unsigned) y12 < (unsigned) size.height )
            {
                uchar *tptr = ptr + y12 * step;
                ICV_HLINE( tptr, x11, x12, color, pix_size );
            }

            if( x21 < size.width && x22 >= 0 )
            {
                x21 = CV_MAX( x21, 0 );
                x22 = CV_MIN( x22, size.width - 1 );

                if( (unsigned) y21 < (unsigned) size.height )
                {
                    uchar *tptr = ptr + y21 * step;
                    ICV_HLINE( tptr, x21, x22, color, pix_size );
                }

                if( (unsigned) y22 < (unsigned) size.height )
                {
                    uchar *tptr = ptr + y22 * step;
                    ICV_HLINE( tptr, x21, x22, color, pix_size );
                }
            }
        }
        dy++;
        err += plus;
        plus += 2;

        mask = (err <= 0) - 1;

        err -= minus & mask;
        dx += mask;
        minus -= mask & 2;
    }
}


/* helper function for thick lines */
static CvPoint
icvCalcWPT( CvPoint p1, CvPoint p2, int lr )
{
    int dx = p1.x - p2.x, dy = p2.y - p1.y;
    double r = dx * dx + dy * dy;
    CvPoint dp = { 0, 0 };

    if( r )
    {
        r = lr * cvInvSqrt( (float) r );
        dp.x = cvRound( dy * r );
        dp.y = cvRound( dx * r );
    }
    return dp;
}


static void
icvThickLine( CvMat* img, CvPoint pt1, CvPoint pt2,
              int thickness, const void* color,
              int connectivity = 8 )
{
    thickness >>= 1;

    if( connectivity == 0 )
        connectivity = 8;

    if( thickness <= 0 )
    {
        icvLine( img, pt1, pt2, color, connectivity );
    }
    else
    {
        CvPoint pt[4];
        CvPoint dp = icvCalcWPT( pt1, pt2, thickness );

        pt[0].x = pt1.x + dp.x;
        pt[0].y = pt1.y + dp.y;
        pt[1].x = pt1.x - dp.x;
        pt[1].y = pt1.y - dp.y;
        pt[2].x = pt2.x - dp.x;
        pt[2].y = pt2.y - dp.y;
        pt[3].x = pt2.x + dp.x;
        pt[3].y = pt2.y + dp.y;

        icvFillConvexPoly( img, pt, 4, color );
        icvFillCircle( img, pt1, thickness, color );
        icvFillCircle( img, pt2, thickness, color );
    }
}


static void
icvPolyLine( CvMat* img, CvPoint *v, int count, int closed,
             int thickness, const void* color, int connectivity )
{
    CV_FUNCNAME("icvPolyLine");

    __BEGIN__;
    
    int i0 = closed ? count - 1 : 0, i;

    assert( img && thickness >= 0 ); 
    assert( v && count >= 0 );

    if( !v )
        CV_ERROR( CV_StsNullPtr, "" );

    if( count > 0 )
    {
        for( i = !closed; i < count; i0 = i, i++ )
        {
            icvThickLine( img, v[i0], v[i], thickness, color, connectivity );
        }
    }

    __END__;
}


static void
icvPolyLineAA( CvMat* img, CvPoint *v, int count, int closed,
               int scale, const void* color )
{

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?