📄 cxdrawing.c
字号:
/* 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;
cvSeqSort( (CvSeq*)edges, icvCmpEdges, 0 );
cvStartReadSeq( (CvSeq*)edges, &reader, 0 );
#ifdef _DEBUG
e = &tmp;
tmp.y0 = INT_MIN;
#endif
for( i = 0; i < total; i++ )
{
CvPolyEdge* e1 = (CvPolyEdge*)(reader.ptr);
#ifdef _DEBUG
assert( e1->y0 < e1->y1 && (i == 0 || icvCmpEdges( e, e1, 0 ) <= 0) );
e = e1;
#endif
y_max = MAX( y_max, e1->y1 );
CV_NEXT_SEQ_ELEM( sizeof(CvPolyEdge), reader );
}
/* start drawing */
tmp.y0 = INT_MAX;
cvSeqPush( (CvSeq*)edges, &tmp );
i = 0;
tmp.next = 0;
cvStartReadSeq( (CvSeq*)edges, &reader, 0 );
e = (CvPolyEdge*)(reader.ptr);
y_max = MIN( y_max, size.height );
for( y = e->y0; y < y_max; y++ )
{
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 + XY_ONE - 1) >> XY_SHIFT;
x2 = x2 >> 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 (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 );
}
__END__;
}
/* draws simple or filled circle */
static void
icvCircle( CvMat* img, CvPoint center, int radius, const void* color, int fill )
{
CvSize size = cvGetMatSize( img );
int step = img->step;
int pix_size = CV_ELEM_SIZE(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 ) \
CV_MEMCPY_CHAR( 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;
if( !fill )
{
ICV_PUT_POINT( tptr0, x11 );
ICV_PUT_POINT( tptr1, x11 );
ICV_PUT_POINT( tptr0, x12 );
ICV_PUT_POINT( tptr1, x12 );
}
else
{
ICV_HLINE( tptr0, x11, x12, color, pix_size );
ICV_HLINE( tptr1, x11, x12, color, pix_size );
}
tptr0 = ptr + y21 * step;
tptr1 = ptr + y22 * step;
if( !fill )
{
ICV_PUT_POINT( tptr0, x21 );
ICV_PUT_POINT( tptr1, x21 );
ICV_PUT_POINT( tptr0, x22 );
ICV_PUT_POINT( tptr1, x22 );
}
else
{
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 )
{
if( fill )
{
x11 = MAX( x11, 0 );
x12 = MIN( x12, size.width - 1 );
}
if( (unsigned)y11 < (unsigned)size.height )
{
uchar *tptr = ptr + y11 * step;
if( !fill )
{
if( x11 >= 0 )
ICV_PUT_POINT( tptr, x11 );
if( x12 < size.width )
ICV_PUT_POINT( tptr, x12 );
}
else
ICV_HLINE( tptr, x11, x12, color, pix_size );
}
if( (unsigned)y12 < (unsigned)size.height )
{
uchar *tptr = ptr + y12 * step;
if( !fill )
{
if( x11 >= 0 )
ICV_PUT_POINT( tptr, x11 );
if( x12 < size.width )
ICV_PUT_POINT( tptr, x12 );
}
else
ICV_HLINE( tptr, x11, x12, color, pix_size );
}
if( x21 < size.width && x22 >= 0 )
{
if( fill )
{
x21 = MAX( x21, 0 );
x22 = MIN( x22, size.width - 1 );
}
if( (unsigned)y21 < (unsigned)size.height )
{
uchar *tptr = ptr + y21 * step;
if( !fill )
{
if( x21 >= 0 )
ICV_PUT_POINT( tptr, x21 );
if( x22 < size.width )
ICV_PUT_POINT( tptr, x22 );
}
else
ICV_HLINE( tptr, x21, x22, color, pix_size );
}
if( (unsigned)y22 < (unsigned)size.height )
{
uchar *tptr = ptr + y22 * step;
if( !fill )
{
if( x21 >= 0 )
ICV_PUT_POINT( tptr, x21 );
if( x22 < size.width )
ICV_PUT_POINT( tptr, x22 );
}
else
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;
}
#undef ICV_PUT_POINT
}
static void
icvThickLine( CvMat* img, CvPoint p0, CvPoint p1, const void* color,
int thickness, int line_type, int flags, int shift )
{
static const double INV_XY_ONE = 1./XY_ONE;
p0.x <<= XY_SHIFT - shift;
p0.y <<= XY_SHIFT - shift;
p1.x <<= XY_SHIFT - shift;
p1.y <<= XY_SHIFT - shift;
if( thickness <= 1 )
{
if( line_type < CV_AA )
{
if( line_type == 1 || line_type == 4 || shift == 0 )
{
p0.x = (p0.x + (XY_ONE>>1)) >> XY_SHIFT;
p0.y = (p0.y + (XY_ONE>>1)) >> XY_SHIFT;
p1.x = (p1.x + (XY_ONE>>1)) >> XY_SHIFT;
p1.y = (p1.y + (XY_ONE>>1)) >> XY_SHIFT;
icvLine( img, p0, p1, color, line_type );
}
else
icvLine2( img, p0, p1, color );
}
else
icvLineAA( img, p0, p1, color );
}
else
{
CvPoint pt[4], dp = {0,0};
double dx = (p0.x - p1.x)*INV_XY_ONE, dy = (p1.y - p0.y)*INV_XY_ONE;
double r = dx * dx + dy * dy;
int i;
thickness <<= XY_SHIFT - 1;
if( fabs(r) > DBL_EPSILON )
{
r = thickness * cvInvSqrt( (float) r );
dp.x = cvRound( dy * r );
dp.y = cvRound( dx * r );
}
pt[0].x = p0.x + dp.x;
pt[0].y = p0.y + dp.y;
pt[1].x = p0.x - dp.x;
pt[1].y = p0.y - dp.y;
pt[2].x = p1.x - dp.x;
pt[2].y = p1.y - dp.y;
pt[3].x = p1.x + dp.x;
pt[3].y = p1.y + dp.y;
icvFillConvexPoly( img, pt, 4, color, line_type, XY_SHIFT );
for( i = 0; i < 2; i++ )
{
if( flags & (i+1) )
{
if( line_type < CV_AA )
{
CvPoint center;
center.x = (p0.x + (XY_ONE>>1)) >> XY_SHIFT;
center.y = (p0.y + (XY_ONE>>1)) >> XY_SHIFT;
icvCircle( img, center, thickness >> XY_SHIFT, color, 1 );
}
else
{
icvEllipseEx( img, p0, cvSize(thickness, thickness),
0, 0, 360, color, -1, line_type );
}
}
p0 = p1;
}
}
}
static void
icvPolyLine( CvMat* img, CvPoint *v, int count, int is_closed,
const void* color, int thickness,
int line_type, int shift )
{
CV_FUNCNAME("icvPolyLine");
__BEGIN__
if( count > 0 )
{
int i = is_closed ? count - 1 : 0;
int flags = 2 + !is_closed;
CvPoint p0;
assert( 0 <= shift && shift <= XY_SHIFT );
assert( img && thickness >= 0 );
assert( v && count >= 0 );
if( !v )
CV_ERROR( CV_StsNullPtr, "" );
p0 = v[i];
for( i = !is_closed; i < count; i++ )
{
CvPoint p = v[i];
icvThickLine( img, p0, p, color, thickness, line_type, flags, shift );
p0 = p;
flags = 2;
}
}
__END__;
}
/****************************************************************************************\
* External functions *
\****************************************************************************************/
CV_IMPL CvScalar cvColorToScalar( double packed_color, int type )
{
CvScalar scalar;
if( CV_MAT_DEPTH( type ) == CV_8U )
{
int icolor = cvRound( packed_color );
if( CV_MAT_CN( type ) > 1 )
{
scalar.val[0] = icolor & 255;
scalar.val[1] = (icolor >> 8) & 255;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -