📄 cxdrawing.c
字号:
*sinval = icvSinTable[angle];
*cosval = icvSinTable[450 - angle];
}
/*
constructs polygon that represents elliptic arc.
*/
CV_IMPL int
cvEllipse2Poly( CvPoint center, CvSize axes, int angle,
int arc_start, int arc_end, CvPoint* pts, int delta )
{
float alpha, beta;
double size_a = axes.width, size_b = axes.height;
double cx = center.x, cy = center.y;
CvPoint *pts_origin = pts;
int i;
while( angle < 0 )
angle += 360;
while( angle > 360 )
angle -= 360;
if( arc_start > arc_end )
{
i = arc_start;
arc_start = arc_end;
arc_end = i;
}
while( arc_start < 0 )
{
arc_start += 360;
arc_end += 360;
}
while( arc_end > 360 )
{
arc_end -= 360;
arc_start -= 360;
}
if( arc_end - arc_start > 360 )
{
arc_start = 0;
arc_end = 360;
}
icvSinCos( angle, &alpha, &beta );
for( i = arc_start; i < arc_end + delta; i += delta )
{
double x, y;
angle = i;
if( angle > arc_end )
angle = arc_end;
if( angle < 0 )
angle += 360;
x = size_a * icvSinTable[450-angle];
y = size_b * icvSinTable[angle];
pts->x = cvRound( cx + x * alpha - y * beta );
pts->y = cvRound( cy - x * beta - y * alpha );
pts += i == arc_start || pts->x != pts[-1].x || pts->y != pts[-1].y;
}
i = (int)(pts - pts_origin);
for( ; i < 2; i++ )
pts_origin[i] = pts_origin[i-1];
return i;
}
static void
icvEllipseEx( CvMat* img, CvPoint center, CvSize axes,
int angle, int arc_start, int arc_end,
const void* color, int thickness, int line_type )
{
CvMemStorage* st = 0;
CV_FUNCNAME( "icvEllipseEx" );
__BEGIN__
CvPoint v[1 << 8];
int count, delta;
if( axes.width < 0 || axes.height < 0 )
CV_ERROR( CV_StsBadSize, "" );
delta = (MAX(axes.width,axes.height)+(XY_ONE>>1))>>XY_SHIFT;
delta = delta < 3 ? 90 : delta < 10 ? 30 : delta < 15 ? 18 : 5;
count = cvEllipse2Poly( center, axes, angle, arc_start, arc_end, v, delta );
if( thickness >= 0 )
{
icvPolyLine( img, v, count, 0, color, thickness, line_type, XY_SHIFT );
}
else if( arc_end - arc_start >= 360 )
{
icvFillConvexPoly( img, v, count, color, line_type, XY_SHIFT );
}
else
{
CvContour* edges;
CvSeq vtx;
CvSeqBlock block;
CV_CALL( st = cvCreateMemStorage( CV_DRAWING_STORAGE_BLOCK ));
CV_CALL( edges = (CvContour*)cvCreateSeq( 0, sizeof(CvContour), sizeof(CvPolyEdge), st ));
v[count++] = center;
CV_CALL( cvMakeSeqHeaderForArray( CV_32SC2, sizeof(CvSeq), sizeof(CvPoint),
v, count, &vtx, &block ));
CV_CALL( icvCollectPolyEdges( img, &vtx, edges, color, line_type, XY_SHIFT, cvPoint(0,0) ));
CV_CALL( icvFillEdgeCollection( img, edges, color ));
}
__END__;
if( st )
cvReleaseMemStorage( &st );
}
/****************************************************************************************\
* Polygons filling *
\****************************************************************************************/
/* helper macros: filling horizontal row */
#define ICV_HLINE( ptr, xl, xr, color, pix_size ) \
{ \
uchar* hline_ptr = (uchar*)(ptr) + (xl)*(pix_size); \
uchar* hline_max_ptr = (uchar*)(ptr) + (xr)*(pix_size); \
\
for( ; hline_ptr <= hline_max_ptr; hline_ptr += (pix_size))\
{ \
int hline_j; \
for( hline_j = 0; hline_j < (pix_size); hline_j++ ) \
{ \
hline_ptr[hline_j] = ((uchar*)color)[hline_j]; \
} \
} \
}
/* filling convex polygon. v - array of vertices, ntps - number of points */
static void
icvFillConvexPoly( CvMat* img, CvPoint *v, int npts, const void* color, int line_type, int shift )
{
struct
{
int idx, di;
int x, dx, ye;
}
edge[2];
int delta = shift ? 1 << (shift - 1) : 0;
int i, y, imin = 0, left = 0, right = 1, x1, x2;
int edges = npts;
int xmin, xmax, ymin, ymax;
uchar* ptr = img->data.ptr;
CvSize size = cvGetMatSize( img );
int pix_size = CV_ELEM_SIZE(img->type);
CvPoint p0;
int delta1, delta2;
if( line_type < CV_AA )
delta1 = delta2 = XY_ONE >> 1;
//delta1 = 0, delta2 = XY_ONE - 1;
else
delta1 = XY_ONE - 1, delta2 = 0;
p0 = v[npts - 1];
p0.x <<= XY_SHIFT - shift;
p0.y <<= XY_SHIFT - shift;
assert( 0 <= shift && shift <= XY_SHIFT );
xmin = xmax = v[0].x;
ymin = ymax = v[0].y;
for( i = 0; i < npts; i++ )
{
CvPoint p = v[i];
if( p.y < ymin )
{
ymin = p.y;
imin = i;
}
ymax = MAX( ymax, p.y );
xmax = MAX( xmax, p.x );
xmin = MIN( xmin, p.x );
p.x <<= XY_SHIFT - shift;
p.y <<= XY_SHIFT - shift;
if( line_type <= 8 )
{
if( shift == 0 )
{
CvPoint pt0, pt1;
pt0.x = p0.x >> XY_SHIFT;
pt0.y = p0.y >> XY_SHIFT;
pt1.x = p.x >> XY_SHIFT;
pt1.y = p.y >> XY_SHIFT;
icvLine( img, pt0, pt1, color, line_type );
}
else
icvLine2( img, p0, p, color );
}
else
icvLineAA( img, p0, p, color );
p0 = p;
}
xmin = (xmin + delta) >> shift;
xmax = (xmax + delta) >> shift;
ymin = (ymin + delta) >> shift;
ymax = (ymax + delta) >> shift;
if( npts < 3 || xmax < 0 || ymax < 0 || xmin >= size.width || ymin >= size.height )
return;
ymax = MIN( ymax, size.height - 1 );
edge[0].idx = edge[1].idx = imin;
edge[0].ye = edge[1].ye = y = ymin;
edge[0].di = 1;
edge[1].di = npts - 1;
ptr += img->step*y;
do
{
if( line_type < CV_AA || y < ymax || y == ymin )
{
for( i = 0; i < 2; i++ )
{
if( y >= edge[i].ye )
{
int idx = edge[i].idx, di = edge[i].di;
int xs = 0, xe, ye, ty = 0;
for(;;)
{
ty = (v[idx].y + delta) >> shift;
if( ty > y || edges == 0 )
break;
xs = v[idx].x;
idx += di;
idx -= ((idx < npts) - 1) & npts; /* idx -= idx >= npts ? npts : 0 */
edges--;
}
ye = ty;
xs <<= XY_SHIFT - shift;
xe = v[idx].x << (XY_SHIFT - shift);
/* no more edges */
if( y >= ye )
return;
edge[i].ye = ye;
edge[i].dx = ((xe - xs)*2 + (ye - y)) / (2 * (ye - y));
edge[i].x = xs;
edge[i].idx = idx;
}
}
}
if( edge[left].x > edge[right].x )
{
left ^= 1;
right ^= 1;
}
x1 = edge[left].x;
x2 = edge[right].x;
if( y >= 0 )
{
int xx1 = (x1 + delta1) >> XY_SHIFT;
int xx2 = (x2 + delta2) >> XY_SHIFT;
if( xx2 >= 0 && xx1 < size.width )
{
if( xx1 < 0 )
xx1 = 0;
if( xx2 >= size.width )
xx2 = size.width - 1;
ICV_HLINE( ptr, xx1, xx2, color, pix_size );
}
}
x1 += edge[left].dx;
x2 += edge[right].dx;
edge[left].x = x1;
edge[right].x = x2;
ptr += img->step;
}
while( ++y <= ymax );
}
/******** Arbitrary polygon **********/
static void
icvCollectPolyEdges( CvMat* img, CvSeq* v, CvContour* edges,
const void* color, int line_type, int shift,
CvPoint offset )
{
int i, count = v->total;
CvRect bounds = edges->rect;
int delta = offset.y + (shift ? 1 << (shift - 1) : 0);
int elem_type = CV_MAT_TYPE(v->flags);
CvSeqReader reader;
CvSeqWriter writer;
cvStartReadSeq( v, &reader, 0 );
cvStartAppendToSeq( (CvSeq*)edges, &writer );
for( i = 0; i < count; i++ )
{
CvPoint pt0, pt1, t0, t1;
CvPolyEdge edge;
CV_READ_EDGE( pt0, pt1, reader );
if( elem_type == CV_32SC2 )
{
pt0.x = (pt0.x + offset.x) << (XY_SHIFT - shift);
pt0.y = (pt0.y + delta) >> shift;
pt1.x = (pt1.x + offset.x) << (XY_SHIFT - shift);
pt1.y = (pt1.y + delta) >> shift;
}
else
{
Cv32suf x, y;
assert( shift == 0 );
x.i = pt0.x; y.i = pt0.y;
pt0.x = cvRound((x.f + offset.x) * XY_ONE);
pt0.y = cvRound(y.f + offset.y);
x.i = pt1.x; y.i = pt1.y;
pt1.x = cvRound((x.f + offset.x) * XY_ONE);
pt1.y = cvRound(y.f + offset.y);
}
if( line_type < CV_AA )
{
t0.y = pt0.y; t1.y = pt1.y;
t0.x = (pt0.x + (XY_ONE >> 1)) >> XY_SHIFT;
t1.x = (pt1.x + (XY_ONE >> 1)) >> XY_SHIFT;
icvLine( img, t0, t1, color, line_type );
}
else
{
t0.x = pt0.x; t1.x = pt1.x;
t0.y = pt0.y << XY_SHIFT;
t1.y = pt1.y << XY_SHIFT;
icvLineAA( img, t0, t1, color );
}
if( pt0.y == pt1.y )
continue;
if( pt0.y > pt1.y )
CV_SWAP( pt0, pt1, t0 );
bounds.y = MIN( bounds.y, pt0.y );
bounds.height = MAX( bounds.height, pt1.y );
if( pt0.x < pt1.x )
{
bounds.x = MIN( bounds.x, pt0.x );
bounds.width = MAX( bounds.width, pt1.x );
}
else
{
bounds.x = MIN( bounds.x, pt1.x );
bounds.width = MAX( bounds.width, pt0.x );
}
edge.y0 = pt0.y;
edge.y1 = pt1.y;
edge.x = pt0.x;
edge.dx = (pt1.x - pt0.x) / (pt1.y - pt0.y);
assert( edge.y0 < edge.y1 );
CV_WRITE_SEQ_ELEM( edge, writer );
}
edges->rect = bounds;
cvEndWriteSeq( &writer );
}
static int
icvCmpEdges( const void* _e1, const void* _e2, void* userdata )
{
CvPolyEdge *e1 = (CvPolyEdge*)_e1, *e2 = (CvPolyEdge*)_e2;
return e1->y0 - e2->y0 ? e1->y0 - e2->y0 :
e1->x - e2->x ? e1->x - e2->x : e1->dx - e2->dx;
}
/**************** helper macros and functions for sequence/contour processing ***********/
static void
icvFillEdgeCollection( CvMat* img, CvContour* edges, const void* color )
{
CvPolyEdge tmp;
int i, y, total = edges->total;
CvSeqReader reader;
CvSize size = cvGetMatSize(img);
CvPolyEdge* e;
int y_max = INT_MIN;
int pix_size = CV_ELEM_SIZE(img->type);
__BEGIN__
memset( &tmp, 0, sizeof(tmp));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -