CV_IMPL int cvMinEnclosingCircle( const void* array, CvPoint2D32f * _center, float *_radius ) { const int max_iters = 100; const float eps = FLT_EPSILON*2; CvPoint2D32f center = { 0, 0 }; float radius = 0; int result = 0; if( _center ) _center->x = _center->y = 0.f; if( _radius ) *_radius = 0; CV_FUNCNAME( "cvMinEnclosingCircle" ); __BEGIN__; CvSeqReader reader; int i, k, count; CvPoint2D32f pts[8]; CvContour contour_header; CvSeqBlock block; CvSeq* sequence = 0; int is_float; if( !_center || !_radius ) CV_ERROR( CV_StsNullPtr, "Null center or radius pointers" ); if( CV_IS_SEQ(array) ) { sequence = (CvSeq*)array; if( !CV_IS_SEQ_POINT_SET( sequence )) CV_ERROR( CV_StsBadArg, "The passed sequence is not a valid contour" ); } else { CV_CALL( sequence = cvPointSeqFromMat( CV_SEQ_KIND_GENERIC, array, &contour_header, &block )); } if( sequence->total <= 0 ) CV_ERROR_FROM_STATUS( CV_BADSIZE_ERR ); CV_CALL( cvStartReadSeq( sequence, &reader, 0 )); count = sequence->total; is_float = CV_SEQ_ELTYPE(sequence) == CV_32FC2; if( !is_float ) { CvPoint *pt_left, *pt_right, *pt_top, *pt_bottom; CvPoint pt; pt_left = pt_right = pt_top = pt_bottom = (CvPoint *)(reader.ptr); CV_READ_SEQ_ELEM( pt, reader ); for( i = 1; i < count; i++ ) { CvPoint* pt_ptr = (CvPoint*)reader.ptr; CV_READ_SEQ_ELEM( pt, reader ); if( pt.x < pt_left->x ) pt_left = pt_ptr; if( pt.x > pt_right->x ) pt_right = pt_ptr; if( pt.y < pt_top->y ) pt_top = pt_ptr; if( pt.y > pt_bottom->y ) pt_bottom = pt_ptr; } pts[0] = cvPointTo32f( *pt_left ); pts[1] = cvPointTo32f( *pt_right ); pts[2] = cvPointTo32f( *pt_top ); pts[3] = cvPointTo32f( *pt_bottom ); } else { CvPoint2D32f *pt_left, *pt_right, *pt_top, *pt_bottom; CvPoint2D32f pt; pt_left = pt_right = pt_top = pt_bottom = (CvPoint2D32f *) (reader.ptr); CV_READ_SEQ_ELEM( pt, reader ); for( i = 1; i < count; i++ ) { CvPoint2D32f* pt_ptr = (CvPoint2D32f*)reader.ptr; CV_READ_SEQ_ELEM( pt, reader ); if( pt.x < pt_left->x ) pt_left = pt_ptr; if( pt.x > pt_right->x ) pt_right = pt_ptr; if( pt.y < pt_top->y ) pt_top = pt_ptr; if( pt.y > pt_bottom->y ) pt_bottom = pt_ptr; } pts[0] = *pt_left; pts[1] = *pt_right; pts[2] = *pt_top; pts[3] = *pt_bottom; } for( k = 0; k < max_iters; k++ ) { double min_delta = 0, delta; CvPoint2D32f ptfl; icvFindEnslosingCicle4pts_32f( pts, ¢er, &radius ); cvStartReadSeq( sequence, &reader, 0 ); for( i = 0; i < count; i++ ) { if( !is_float ) { ptfl.x = (float)((CvPoint*)reader.ptr)->x; ptfl.y = (float)((CvPoint*)reader.ptr)->y; } else { ptfl = *(CvPoint2D32f*)reader.ptr; } CV_NEXT_SEQ_ELEM( sequence->elem_size, reader ); delta = icvIsPtInCircle( ptfl, center, radius ); if( delta < min_delta ) { min_delta = delta; pts[3] = ptfl; } } result = min_delta >= 0; if( result ) break; } if( !result ) { cvStartReadSeq( sequence, &reader, 0 ); radius = 0.f; for( i = 0; i < count; i++ ) { CvPoint2D32f ptfl; float t, dx, dy; if( !is_float ) { ptfl.x = (float)((CvPoint*)reader.ptr)->x; ptfl.y = (float)((CvPoint*)reader.ptr)->y; } else { ptfl = *(CvPoint2D32f*)reader.ptr; } CV_NEXT_SEQ_ELEM( sequence->elem_size, reader ); dx = center.x - ptfl.x; dy = center.y - ptfl.y; t = dx*dx + dy*dy; radius = MAX(radius,t); } radius = (float)(sqrt(radius)*(1 + eps)); result = 1; } __END__; *_center = center; *_radius = radius; return result; }
CV_IMPL void cvMinEnclosingCircle( CvSeq * sequence, CvPoint2D32f * _center, float *_radius ) { const int max_iters = 20; CvSeqReader reader; int i, k, count; CvPoint *pt_left, *pt_right, *pt_top, *pt_bottom; CvPoint pt; CvPoint2D32f center = { 0, 0 }; CvPoint2D32f pts[8]; float radius = 0; if( _center ) _center->x = _center->y = 0.f; if( _radius ) *_radius = 0; CV_FUNCNAME( "cvMinEnclosingCircle" ); __BEGIN__; if( !sequence || !_center || !_radius ) CV_ERROR_FROM_STATUS( CV_NULLPTR_ERR ); if( sequence->total <= 0 ) CV_ERROR_FROM_STATUS( CV_BADSIZE_ERR ); if( !CV_IS_SEQ_POINT_SET( sequence )) CV_ERROR_FROM_STATUS( CV_BADFLAG_ERR ); CV_CALL( cvStartReadSeq( sequence, &reader, 0 )); pt_left = pt_right = pt_top = pt_bottom = (CvPoint *) (reader.ptr); CV_READ_SEQ_ELEM( pt, reader ); count = sequence->total; for( i = 1; i < count; i++ ) { CvPoint *pt_ptr = (CvPoint *) (reader.ptr); CvPoint pt; CV_READ_SEQ_ELEM( pt, reader ); if( pt.x < pt_left->x ) pt_left = pt_ptr; if( pt.x > pt_right->x ) pt_right = pt_ptr; if( pt.y < pt_top->y ) pt_top = pt_ptr; if( pt.y > pt_bottom->y ) pt_bottom = pt_ptr; } pts[0] = icvCvtPoint32s_32f( *pt_left ); pts[1] = icvCvtPoint32s_32f( *pt_right ); pts[2] = icvCvtPoint32s_32f( *pt_top ); pts[3] = icvCvtPoint32s_32f( *pt_bottom ); for( k = 0; k < max_iters; k++ ) { icvFindEnslosingCicle4pts_32f( pts, ¢er, &radius ); cvStartReadSeq( sequence, &reader, 0 ); for( i = 0; i < count; i++ ) { CvPoint pt; CvPoint2D32f ptfl; CV_READ_SEQ_ELEM( pt, reader ); ptfl = icvCvtPoint32s_32f( pt ); if( !icvIsPtInCircle( ptfl, center, radius )) { pts[3] = ptfl; break; } } if( i == count ) break; } __CLEANUP__; __END__; *_center = center; *_radius = radius; }
CV_IMPL int cvMinEnclosingCircle( const void* array, CvPoint2D32f * _center, float *_radius ) { const int max_iters = 100; const float eps = FLT_EPSILON*2; CvPoint2D32f center = { 0, 0 }; float radius = 0; int result = 0; if( _center ) _center->x = _center->y = 0.f; if( _radius ) *_radius = 0; CvSeqReader reader; int k, count; CvPoint2D32f pts[8]; CvContour contour_header; CvSeqBlock block; CvSeq* sequence = 0; int is_float; if( !_center || !_radius ) CV_Error( CV_StsNullPtr, "Null center or radius pointers" ); if( CV_IS_SEQ(array) ) { sequence = (CvSeq*)array; if( !CV_IS_SEQ_POINT_SET( sequence )) CV_Error( CV_StsBadArg, "The passed sequence is not a valid contour" ); } else { sequence = cvPointSeqFromMat( CV_SEQ_KIND_GENERIC, array, &contour_header, &block ); } if( sequence->total <= 0 ) CV_Error( CV_StsBadSize, "" ); cvStartReadSeq( sequence, &reader, 0 ); count = sequence->total; is_float = CV_SEQ_ELTYPE(sequence) == CV_32FC2; if( !is_float ) { CvPoint *pt_left, *pt_right, *pt_top, *pt_bottom; CvPoint pt; pt_left = pt_right = pt_top = pt_bottom = (CvPoint *)(reader.ptr); CV_READ_SEQ_ELEM( pt, reader ); for(int i = 1; i < count; i++ ) { CvPoint* pt_ptr = (CvPoint*)reader.ptr; CV_READ_SEQ_ELEM( pt, reader ); if( pt.x < pt_left->x ) pt_left = pt_ptr; if( pt.x > pt_right->x ) pt_right = pt_ptr; if( pt.y < pt_top->y ) pt_top = pt_ptr; if( pt.y > pt_bottom->y ) pt_bottom = pt_ptr; } pts[0] = cvPointTo32f( *pt_left ); pts[1] = cvPointTo32f( *pt_right ); pts[2] = cvPointTo32f( *pt_top ); pts[3] = cvPointTo32f( *pt_bottom ); } else { CvPoint2D32f *pt_left, *pt_right, *pt_top, *pt_bottom; CvPoint2D32f pt; pt_left = pt_right = pt_top = pt_bottom = (CvPoint2D32f *) (reader.ptr); CV_READ_SEQ_ELEM( pt, reader ); for(int i = 1; i < count; i++ ) { CvPoint2D32f* pt_ptr = (CvPoint2D32f*)reader.ptr; CV_READ_SEQ_ELEM( pt, reader ); if( pt.x < pt_left->x ) pt_left = pt_ptr; if( pt.x > pt_right->x ) pt_right = pt_ptr; if( pt.y < pt_top->y ) pt_top = pt_ptr; if( pt.y > pt_bottom->y ) pt_bottom = pt_ptr; } pts[0] = *pt_left; pts[1] = *pt_right; pts[2] = *pt_top; pts[3] = *pt_bottom; } for( k = 0; k < max_iters; k++ ) { double min_delta = 0, delta; CvPoint2D32f ptfl, farAway = { 0, 0}; /*only for first iteration because the alg is repared at the loop's foot*/ if(k==0) icvFindEnslosingCicle4pts_32f( pts, ¢er, &radius ); cvStartReadSeq( sequence, &reader, 0 ); for(int i = 0; i < count; i++ ) { if( !is_float ) { ptfl.x = (float)((CvPoint*)reader.ptr)->x; ptfl.y = (float)((CvPoint*)reader.ptr)->y; } else { ptfl = *(CvPoint2D32f*)reader.ptr; } CV_NEXT_SEQ_ELEM( sequence->elem_size, reader ); delta = icvIsPtInCircle( ptfl, center, radius ); if( delta < min_delta ) { min_delta = delta; farAway = ptfl; } } result = min_delta >= 0; if( result ) break; CvPoint2D32f ptsCopy[4]; /* find good replacement partner for the point which is at most far away, starting with the one that lays in the actual circle (i=3) */ for(int i = 3; i >=0; i-- ) { for(int j = 0; j < 4; j++ ) { ptsCopy[j]=(i != j)? pts[j]: farAway; } icvFindEnslosingCicle4pts_32f(ptsCopy, ¢er, &radius ); if( icvIsPtInCircle( pts[i], center, radius )>=0){ // replaced one again in the new circle? pts[i] = farAway; break; } } } if( !result ) { cvStartReadSeq( sequence, &reader, 0 ); radius = 0.f; for(int i = 0; i < count; i++ ) { CvPoint2D32f ptfl; float t, dx, dy; if( !is_float ) { ptfl.x = (float)((CvPoint*)reader.ptr)->x; ptfl.y = (float)((CvPoint*)reader.ptr)->y; } else { ptfl = *(CvPoint2D32f*)reader.ptr; } CV_NEXT_SEQ_ELEM( sequence->elem_size, reader ); dx = center.x - ptfl.x; dy = center.y - ptfl.y; t = dx*dx + dy*dy; radius = MAX(radius,t); } radius = (float)(sqrt(radius)*(1 + eps)); result = 1; } *_center = center; *_radius = radius; return result; }