contrib/brl/bseg/brip/brip_label_equivalence.cxx
Go to the documentation of this file.
00001 #include "brip_label_equivalence.h"
00002 //:
00003 // \file
00004 
00005 #include <vcl_utility.h>
00006 #include <vcl_iostream.h>
00007 
00008 //: add a label pair equivalence
00009 void brip_label_equivalence::add_label_pair(unsigned la, unsigned lb)
00010 {
00011   vcl_pair<vcl_set<unsigned>::iterator, bool> result;
00012   result = forward_pairs_[la].insert(lb);
00013   if (result.second)
00014     if (la>max_label_)
00015       max_label_ = la;
00016   result =  reverse_pairs_[lb].insert(la);
00017   if (result.second)
00018     if (la>max_label_)
00019       max_label_ = lb;
00020 }
00021 //: find all the individual labels and determine the largest label
00022 vcl_set<unsigned> brip_label_equivalence::labels() const
00023 {
00024   vcl_set<unsigned> labs;
00025   vcl_map<unsigned, vcl_set<unsigned> >::const_iterator mit =
00026     forward_pairs_.begin();
00027   for (; mit != forward_pairs_.end(); ++mit) {
00028     labs.insert((*mit).first);
00029   }
00030   mit = reverse_pairs_.begin();
00031   for (; mit != reverse_pairs_.end(); ++mit) {
00032     labs.insert((*mit).first);
00033   }
00034   return labs;
00035 }
00036 
00037 bool brip_label_equivalence::
00038 merge_equivalence(vcl_map<unsigned int, vcl_set<unsigned int> >& tab,
00039                   unsigned int cur_label,
00040                   unsigned int label)
00041 {
00042   vcl_map<unsigned , vcl_set<unsigned> >::iterator hashi;
00043   //If we can't find the label in tab then there are no equivalences to be merged
00044   hashi = tab.find(label);
00045   if (hashi == tab.end()) {
00046     return false;
00047   }
00048   //We did find label, and labels is a set of equivalent labels
00049   vcl_set<unsigned>& labels = hashi->second;
00050 
00051   //If the set is empty then nothing to do
00052   unsigned len = labels.size();
00053   if (!len)
00054     return false;
00055 
00056   hashi = equivalence_sets_.find(cur_label);
00057   if ( hashi == equivalence_sets_.end())
00058   {
00059     //We didn't find any equivalent labels for cur_label so we initialize a new one
00060     //and insert it into equivalence_sets
00061     equivalence_sets_[cur_label] = vcl_set<unsigned>();
00062   }
00063 
00064   for (vcl_set<unsigned>::iterator lit = labels.begin();
00065        lit != labels.end(); ++lit)
00066     equivalence_sets_[cur_label].insert(*lit);
00067   return true;
00068 }
00069 
00070 //----------------------------------------------------------------
00071 //: Find the next label not accounted for in the current equivalence set.
00072 //  The set of labels is searched to find a label larger than label, but
00073 //  not in the set, labels.
00074 bool brip_label_equivalence::get_next_label(vcl_set<unsigned> const& labels,
00075                                             unsigned int& label)
00076 {
00077   //If the set labels is null then
00078   //just return the next larger label (if less than max_region_label_)
00079   unsigned int tmp = label+1;
00080   if (!labels.size())
00081     if (tmp<max_label_)
00082     {
00083       label = tmp;
00084       return true;
00085     }
00086 
00087   //The set is not empty, so search for a label not found in the
00088   //set.
00089   for (unsigned int i = tmp; i<=max_label_; i++)
00090   {
00091     vcl_set<unsigned>::const_iterator sit=labels.find(i);
00092     if (sit==labels.end()){
00093       label = i;
00094       return true;
00095     }
00096   }
00097   return false;
00098 }
00099 
00100 
00101 void brip_label_equivalence::transitive_closure()
00102 {
00103   vcl_set<unsigned> labs = this->labels();
00104   if (labs.size()<=1)
00105     return;
00106   unsigned cur_label = *(labs.begin());
00107 
00108   //the iterator for equivalence_sets_
00109   vcl_map<unsigned , vcl_set<unsigned > >::iterator mei;
00110   while (true)
00111   {
00112     bool merging = true;
00113     unsigned i = cur_label;
00114     vcl_set<unsigned> cur_set;
00115     int len = 0;
00116     int old_len;
00117     while (merging)
00118     {
00119       old_len = len;
00120       merging = false;
00121       //find label equivalence in the forward map
00122       bool find_forward =
00123         this->merge_equivalence(forward_pairs_, cur_label, i);
00124       vcl_map<unsigned, vcl_set<unsigned> >::iterator sit;
00125       if (find_forward)
00126       {
00127         sit = forward_pairs_.find(i);
00128         if (sit!=forward_pairs_.end())
00129           forward_pairs_.erase(sit);
00130       }
00131 #if 0
00132       if (find_forward)
00133         vcl_cout << "merged forward pairs on label " << i << '\n' << vcl_flush;
00134 #endif
00135       //find label equivalence in the reverse map
00136       bool find_reverse =
00137         this->merge_equivalence(reverse_pairs_, cur_label, i);
00138       if (find_reverse)
00139       {
00140         sit = reverse_pairs_.find(i);
00141         if (sit!=reverse_pairs_.end())
00142           reverse_pairs_.erase(sit);
00143       }
00144 #if 0
00145       if (find_reverse)
00146         vcl_cout << "merged reverse pairs on label " << i << '\n' << vcl_flush;
00147 #endif
00148       //At this point we may have established or added to the equivalence set
00149       //for cur_label stored in equivalence_sets[cur_label]
00150       //we check if we have
00151       mei = equivalence_sets_.find(cur_label);
00152       if (mei == equivalence_sets_.end()) continue;
00153       //If we don't find cur_label, it means that we couldn't find label i
00154       //in either forward_pairs or reverse_pairs, so we need
00155       //to get a new i.
00156 
00157       //We did find a growing equivalence set, cur_set, but it might be null
00158       //or empty
00159       cur_set =equivalence_sets_[cur_label];
00160       len = cur_set.size();
00161       if (!len) continue;
00162 
00163       //Now we check cur_set has actually been extended.
00164 
00165       if (len > old_len)  i = cur_label;
00166       // Limit the size of an equivalence class
00167       if (len > 200)
00168       {
00169         merging = false;
00170         continue;
00171       }
00172       //Get the next larger label from cur_set
00173       //so that we can insert its equivalent labels
00174       for (vcl_set<unsigned>::iterator cit = cur_set.begin();
00175            cit != cur_set.end() && !merging; ++cit)
00176         if (*cit>i)
00177         {
00178           i = *cit;
00179           merging = true;
00180         }
00181       //If we reach here with merging = false then we have finished the
00182       //current equivalence class
00183     }
00184     //Find the next largest label that isn't in cur_set to seed the
00185     //next equivalence class
00186     if (!get_next_label(cur_set, cur_label)) return;
00187 #if 0
00188     vcl_cout << "Getting next label to seed equivalence "
00189              << cur_label << '\n' << vcl_flush;
00190 #endif
00191   }
00192 }