This function splits the input sequence or set into one or more equivalence classes. is_equal(a,b,...) returns non-zero if the two sequence elements belong to the same class. The function returns sequence of integers - 0-based class indexes for each element. The algorithm is described in "Introduction to Algorithms" by Cormen, Leiserson and Rivest, chapter "Data structures for disjoint sets"
| 2320 | // The algorithm is described in "Introduction to Algorithms" |
| 2321 | // by Cormen, Leiserson and Rivest, chapter "Data structures for disjoint sets" |
| 2322 | CV_IMPL int |
| 2323 | cvSeqPartition( const CvSeq* seq, CvMemStorage* storage, CvSeq** labels, |
| 2324 | CvCmpFunc is_equal, void* userdata ) |
| 2325 | { |
| 2326 | CvSeq* result = 0; |
| 2327 | CvMemStorage* temp_storage = 0; |
| 2328 | int class_idx = 0; |
| 2329 | |
| 2330 | CvSeqWriter writer; |
| 2331 | CvSeqReader reader, reader0; |
| 2332 | CvSeq* nodes; |
| 2333 | int i, j; |
| 2334 | int is_set; |
| 2335 | |
| 2336 | if( !labels ) |
| 2337 | CV_Error( CV_StsNullPtr, "" ); |
| 2338 | |
| 2339 | if( !seq || !is_equal ) |
| 2340 | CV_Error( CV_StsNullPtr, "" ); |
| 2341 | |
| 2342 | if( !storage ) |
| 2343 | storage = seq->storage; |
| 2344 | |
| 2345 | if( !storage ) |
| 2346 | CV_Error( CV_StsNullPtr, "" ); |
| 2347 | |
| 2348 | is_set = CV_IS_SET(seq); |
| 2349 | |
| 2350 | temp_storage = cvCreateChildMemStorage( storage ); |
| 2351 | |
| 2352 | nodes = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvPTreeNode), temp_storage ); |
| 2353 | |
| 2354 | cvStartReadSeq( seq, &reader ); |
| 2355 | memset( &writer, 0, sizeof(writer)); |
| 2356 | cvStartAppendToSeq( nodes, &writer ); |
| 2357 | |
| 2358 | // Initial O(N) pass. Make a forest of single-vertex trees. |
| 2359 | for( i = 0; i < seq->total; i++ ) |
| 2360 | { |
| 2361 | CvPTreeNode node = { 0, 0, 0 }; |
| 2362 | if( !is_set || CV_IS_SET_ELEM( reader.ptr )) |
| 2363 | node.element = reader.ptr; |
| 2364 | CV_WRITE_SEQ_ELEM( node, writer ); |
| 2365 | CV_NEXT_SEQ_ELEM( seq->elem_size, reader ); |
| 2366 | } |
| 2367 | |
| 2368 | cvEndWriteSeq( &writer ); |
| 2369 | |
| 2370 | // Because in the next loop we will iterate |
| 2371 | // through all the sequence nodes each time, |
| 2372 | // we do not need to initialize reader every time: |
| 2373 | cvStartReadSeq( nodes, &reader ); |
| 2374 | cvStartReadSeq( nodes, &reader0 ); |
| 2375 | |
| 2376 | // The main O(N^2) pass. Merge connected components. |
| 2377 | for( i = 0; i < nodes->total; i++ ) |
| 2378 | { |
| 2379 | CvPTreeNode* node = (CvPTreeNode*)(reader0.ptr); |
nothing calls this directly
no test coverage detected