static CvSubdiv2DEdge cvSubdiv2DMakeEdge( CvSubdiv2D * subdiv ) { CvQuadEdge2D *edge = 0; CvSubdiv2DEdge edgehandle = 0; CV_FUNCNAME( "cvSubdiv2DMakeEdge" ); __BEGIN__; if( !subdiv ) CV_ERROR( CV_StsNullPtr, "" ); edge = (CvQuadEdge2D*)cvSetNew( (CvSet*)subdiv->edges ); CV_CHECK(); memset( edge->pt, 0, sizeof( edge->pt )); edgehandle = (CvSubdiv2DEdge) edge; edge->next[0] = edgehandle; edge->next[1] = edgehandle + 3; edge->next[2] = edgehandle + 2; edge->next[3] = edgehandle + 1; subdiv->quad_edges++; __END__; return edgehandle; }
CV_IMPL void cvStartReadChainPoints( CvChain * chain, CvChainPtReader * reader ) { int i; CV_FUNCNAME( "cvStartReadChainPoints" ); __BEGIN__; if( !chain || !reader ) CV_ERROR( CV_StsNullPtr, "" ); if( chain->elem_size != 1 || chain->header_size < (int)sizeof(CvChain)) CV_ERROR_FROM_STATUS( CV_BADSIZE_ERR ); cvStartReadSeq( (CvSeq *) chain, (CvSeqReader *) reader, 0 ); CV_CHECK(); reader->pt = chain->origin; for( i = 0; i < 8; i++ ) { reader->deltas[i][0] = (char) icvCodeDeltas[i].x; reader->deltas[i][1] = (char) icvCodeDeltas[i].y; } __END__; }
CV_IMPL CvSubdiv2DPoint * cvSubdivDelaunay2DInsert( CvSubdiv2D * subdiv, CvPoint2D32f pt ) { CvSubdiv2DPoint *point = 0; CvSubdiv2DPointLocation location = CV_PTLOC_ERROR; CvSubdiv2DPoint *curr_point = 0, *first_point = 0; CvSubdiv2DEdge curr_edge = 0, deleted_edge = 0, base_edge = 0; int i, max_edges; CV_FUNCNAME( "cvSubdivDelaunay2DInsert" ); __BEGIN__; if( !subdiv ) CV_ERROR( CV_StsNullPtr, "" ); if( !CV_IS_SUBDIV2D(subdiv) ) CV_ERROR_FROM_STATUS( CV_BADFLAG_ERR ); location = cvSubdiv2DLocate( subdiv, pt, &curr_edge, &curr_point ); switch (location) { case CV_PTLOC_ERROR: CV_ERROR_FROM_STATUS( CV_BADSIZE_ERR ); case CV_PTLOC_OUTSIDE_RECT: CV_ERROR_FROM_STATUS( CV_BADRANGE_ERR ); case CV_PTLOC_VERTEX: point = curr_point; break; case CV_PTLOC_ON_EDGE: deleted_edge = curr_edge; subdiv->recent_edge = curr_edge = cvSubdiv2DGetEdge( curr_edge, CV_PREV_AROUND_ORG ); cvSubdiv2DDeleteEdge( subdiv, deleted_edge ); /* no break */ case CV_PTLOC_INSIDE: assert( curr_edge != 0 ); subdiv->is_geometry_valid = 0; curr_point = cvSubdiv2DAddPoint( subdiv, pt, 0 ); CV_CHECK(); base_edge = cvSubdiv2DMakeEdge( subdiv ); first_point = cvSubdiv2DEdgeOrg( curr_edge ); cvSubdiv2DSetEdgePoints( base_edge, first_point, curr_point ); cvSubdiv2DSplice( base_edge, curr_edge ); do { base_edge = cvSubdiv2DConnectEdges( subdiv, curr_edge, cvSubdiv2DSymEdge( base_edge )); curr_edge = cvSubdiv2DGetEdge( base_edge, CV_PREV_AROUND_ORG ); } while( cvSubdiv2DEdgeDst( curr_edge ) != first_point ); curr_edge = cvSubdiv2DGetEdge( base_edge, CV_PREV_AROUND_ORG ); max_edges = subdiv->quad_edges * 4; for( i = 0; i < max_edges; i++ ) { CvSubdiv2DPoint *temp_dst = 0, *curr_org = 0, *curr_dst = 0; CvSubdiv2DEdge temp_edge = cvSubdiv2DGetEdge( curr_edge, CV_PREV_AROUND_ORG ); temp_dst = cvSubdiv2DEdgeDst( temp_edge ); curr_org = cvSubdiv2DEdgeOrg( curr_edge ); curr_dst = cvSubdiv2DEdgeDst( curr_edge ); if( icvIsRightOf( temp_dst->pt, curr_edge ) > 0 && icvIsPtInCircle3( curr_org->pt, temp_dst->pt, curr_dst->pt, curr_point->pt ) < 0 ) { cvSubdiv2DSwapEdges( curr_edge ); curr_edge = cvSubdiv2DGetEdge( curr_edge, CV_PREV_AROUND_ORG ); } else if( curr_org == first_point ) { break; } else { curr_edge = cvSubdiv2DGetEdge( cvSubdiv2DNextEdge( curr_edge ), CV_PREV_AROUND_LEFT ); } } break; default: assert( 0 ); CV_ERROR_FROM_STATUS( CV_NOTDEFINED_ERR ); } point = curr_point; __END__; //icvSubdiv2DCheck( subdiv ); return point; }
/* Initializes scanner structure. Prepare image for scanning ( clear borders and convert all pixels to 0-1. */ CV_IMPL CvContourScanner cvStartFindContours( void* _img, CvMemStorage* storage, int header_size, int mode, int method, CvPoint offset ) { int y; int step; CvSize size; uchar *img = 0; CvContourScanner scanner = 0; CvMat stub, *mat = (CvMat*)_img; CV_FUNCNAME( "cvStartFindContours" ); __BEGIN__; if( !storage ) CV_ERROR( CV_StsNullPtr, "" ); CV_CALL( mat = cvGetMat( mat, &stub )); if( !CV_IS_MASK_ARR( mat )) CV_ERROR( CV_StsUnsupportedFormat, "[Start]FindContours support only 8uC1 images" ); size = cvSize( mat->width, mat->height ); step = mat->step; img = (uchar*)(mat->data.ptr); if( method < 0 || method > CV_CHAIN_APPROX_TC89_KCOS ) CV_ERROR_FROM_STATUS( CV_BADRANGE_ERR ); if( header_size < (int) (method == CV_CHAIN_CODE ? sizeof( CvChain ) : sizeof( CvContour ))) CV_ERROR_FROM_STATUS( CV_BADSIZE_ERR ); scanner = (CvContourScanner)cvAlloc( sizeof( *scanner )); if( !scanner ) CV_ERROR_FROM_STATUS( CV_OUTOFMEM_ERR ); memset( scanner, 0, sizeof( *scanner )); scanner->storage1 = scanner->storage2 = storage; scanner->img0 = (char *) img; scanner->img = (char *) (img + step); scanner->img_step = step; scanner->img_size.width = size.width - 1; /* exclude rightest column */ scanner->img_size.height = size.height - 1; /* exclude bottomost row */ scanner->mode = mode; scanner->offset = offset; scanner->pt.x = scanner->pt.y = 1; scanner->lnbd.x = 0; scanner->lnbd.y = 1; scanner->nbd = 2; scanner->mode = (int) mode; scanner->frame_info.contour = &(scanner->frame); scanner->frame_info.is_hole = 1; scanner->frame_info.next = 0; scanner->frame_info.parent = 0; scanner->frame_info.rect = cvRect( 0, 0, size.width, size.height ); scanner->l_cinfo = 0; scanner->subst_flag = 0; scanner->frame.flags = CV_SEQ_FLAG_HOLE; scanner->approx_method2 = scanner->approx_method1 = method; if( method == CV_CHAIN_APPROX_TC89_L1 || method == CV_CHAIN_APPROX_TC89_KCOS ) scanner->approx_method1 = CV_CHAIN_CODE; if( scanner->approx_method1 == CV_CHAIN_CODE ) { scanner->seq_type1 = CV_SEQ_CHAIN_CONTOUR; scanner->header_size1 = scanner->approx_method1 == scanner->approx_method2 ? header_size : sizeof( CvChain ); scanner->elem_size1 = sizeof( char ); } else { scanner->seq_type1 = CV_SEQ_POLYGON; scanner->header_size1 = scanner->approx_method1 == scanner->approx_method2 ? header_size : sizeof( CvContour ); scanner->elem_size1 = sizeof( CvPoint ); } scanner->header_size2 = header_size; if( scanner->approx_method2 == CV_CHAIN_CODE ) { scanner->seq_type2 = scanner->seq_type1; scanner->elem_size2 = scanner->elem_size1; } else { scanner->seq_type2 = CV_SEQ_POLYGON; scanner->elem_size2 = sizeof( CvPoint ); } scanner->seq_type1 = scanner->approx_method1 == CV_CHAIN_CODE ? CV_SEQ_CHAIN_CONTOUR : CV_SEQ_POLYGON; scanner->seq_type2 = scanner->approx_method2 == CV_CHAIN_CODE ? CV_SEQ_CHAIN_CONTOUR : CV_SEQ_POLYGON; cvSaveMemStoragePos( storage, &(scanner->initial_pos) ); if( method > CV_CHAIN_APPROX_SIMPLE ) { scanner->storage1 = cvCreateChildMemStorage( scanner->storage2 ); } if( mode > CV_RETR_LIST ) { scanner->cinfo_storage = cvCreateChildMemStorage( scanner->storage2 ); scanner->cinfo_set = cvCreateSet( 0, sizeof( CvSet ), sizeof( _CvContourInfo ), scanner->cinfo_storage ); if( scanner->cinfo_storage == 0 || scanner->cinfo_set == 0 ) CV_ERROR_FROM_STATUS( CV_OUTOFMEM_ERR ); } /* make zero borders */ memset( img, 0, size.width ); memset( img + step * (size.height - 1), 0, size.width ); for( y = 1, img += step; y < size.height - 1; y++, img += step ) { img[0] = img[size.width - 1] = 0; } /* converts all pixels to 0 or 1 */ cvThreshold( mat, mat, 0, 1, CV_THRESH_BINARY ); CV_CHECK(); __END__; if( cvGetErrStatus() < 0 ) cvFree( &scanner ); return scanner; }