contrib/oxl/mvl/PairMatchSet.cxx
Go to the documentation of this file.
00001 // This is oxl/mvl/PairMatchSet.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 //:
00006 // \file
00007 
00008 #include "PairMatchSet.h"
00009 
00010 #include <vcl_cstdlib.h>
00011 #include <vcl_cassert.h>
00012 #include <vcl_iostream.h>
00013 #include <vcl_vector.h>
00014 
00015 #include <mvl/MatchSet.h>
00016 
00017 PairMatchSet::iterator PairMatchSet::iterator::operator++ (int /*postfix*/)
00018 {
00019   vcl_abort();
00020   return *this;
00021 }
00022 
00023 //: Construct a PairMatchSet for values of $i_1$ between 0 and size.
00024 PairMatchSet::PairMatchSet(unsigned size):
00025   matches_(size)
00026 {
00027   clear();
00028 }
00029 
00030 //: Destructor
00031 PairMatchSet::~PairMatchSet()
00032 {
00033 }
00034 
00035 // == OPERATIONS ==
00036 
00037 PairMatchSet::PairMatchSet(const PairMatchSet& that):
00038   MatchSet(),
00039   matches_(that.matches_),
00040   match_count_(that.match_count_)
00041 {
00042 }
00043 
00044 PairMatchSet& PairMatchSet::operator=(const PairMatchSet& that)
00045 {
00046   matches_ = that.matches_;
00047   match_count_ = that.match_count_;
00048   return *this;
00049 }
00050 
00051 void PairMatchSet::update_feature_match_data()
00052 {
00053   assert(false);
00054 }
00055 
00056 //: Add the pair (i1, i2) to the match set.
00057 // If i1 had an existing match it is overwritten.
00058 bool PairMatchSet::add_match(int i1, int i2)
00059 {
00060   if ((unsigned)i1 >= matches_.size()) {
00061     vcl_cerr << "PairMatchSet: add_match(" << i1 << ") greater than size " << matches_.size() << vcl_endl;
00062     vcl_abort();
00063     return false;
00064   }
00065   bool had_nomatch = (matches_[i1] == NoMatch);
00066   bool new_nomatch = (i2 == NoMatch);
00067   matches_[i1] = i2;
00068   if (had_nomatch && !new_nomatch)
00069     ++match_count_;
00070   return true;
00071 }
00072 
00073 //: Remove any match for i1.
00074 //  Specifically, remove tuples whose first element is i1.
00075 void PairMatchSet::clear_match_1(int i1)
00076 {
00077   if ((unsigned)i1 >= matches_.size()) {
00078     vcl_cerr << "PairMatchSet: clear squawwk\n";
00079     return;
00080   }
00081   int& i2 = matches_[i1];
00082   if (i2 != MatchSet::NoMatch) {
00083     assert(match_count_ > 0);
00084     --match_count_;
00085   }
00086 
00087   i2 = MatchSet::NoMatch;
00088 }
00089 
00090 //: Return any match for i1.
00091 //  Specifically, return the second element of any tuple whose first element is i1.
00092 int PairMatchSet::get_match_12(int i1) const
00093 {
00094   if (i1 == MatchSet::NoMatch)
00095     return MatchSet::NoMatch;
00096 
00097   if ((unsigned)i1 >= matches_.size()) {
00098     vcl_cerr << "PairMatchSet::get_match_12() -- i1 = " << i1 << " >= matches_.size() = " << matches_.size() << vcl_endl;
00099     vcl_abort();
00100     return -1;
00101   }
00102 
00103   return matches_[i1];
00104 }
00105 
00106 //: Return any match for i2.
00107 //  Specifically, return the first element of any tuple whose second element is
00108 //  i2.  This is currently O(n) in the number of matches, consider adding an
00109 //  index to this class if you use it a lot.
00110 int PairMatchSet::get_match_21(int i2) const
00111 {
00112   for (unsigned i = 0; i < matches_.size(); ++i)
00113     if (matches_[i] == i2)
00114       return i;
00115   return MatchSet::NoMatch;
00116 }
00117 
00118 // - Allows selection of a given match.  Use the iterator instead.
00119 bool PairMatchSet::get_match(int c, int* i1, int* i2) const
00120 {
00121   if (c >= size())
00122     return false;
00123 
00124   *i1 = c;
00125   *i2 = get_match_12(*i1);
00126 
00127   return true;
00128 }
00129 
00130 //: Empty this match set.
00131 void PairMatchSet::clear()
00132 {
00133   for (unsigned i = 0; i < matches_.size(); ++i)
00134     matches_[i] = MatchSet::NoMatch;
00135   match_count_ = 0;
00136 }
00137 
00138 //: Set this match set to contain matches (i,i) for i=0..size
00139 void PairMatchSet::set_identity()
00140 {
00141   for (unsigned i = 0; i < matches_.size(); ++i)
00142     matches_[i] = i;
00143   match_count_ = matches_.size();
00144 }
00145 
00146 //: Count the number of matches in this set
00147 int PairMatchSet::compute_match_count()
00148 {
00149   match_count_ = 0;
00150   for (unsigned i = 0; i < matches_.size(); ++i)
00151     if (matches_[i] != MatchSet::NoMatch)
00152       ++match_count_;
00153 
00154   return match_count_;
00155 }
00156 
00157 //: Return the maximum allowed value of i1.
00158 int PairMatchSet::size() const
00159 {
00160   return matches_.size();
00161 }
00162 
00163 //: Set the maximum allowed value of i1 to size.
00164 void PairMatchSet::set_size(unsigned newsize)
00165 {
00166   if (newsize != matches_.size())
00167     matches_ = vcl_vector<int>(newsize, NoMatch);
00168 }
00169 
00170 void PairMatchSet::update(const vcl_vector<bool>& inliers)
00171 {
00172   if (inliers.size() != count()) {
00173     vcl_cerr << "PairMatchSet::update() -- This matchset is not the same length as the inliers\n";
00174     vcl_abort();
00175   }
00176 
00177   int n = 0;
00178   for (PairMatchSet::iterator match (*this); match; match.next(), ++n)
00179     if (!inliers[n])
00180       clear_match_1(match.get_i1());
00181 }
00182 
00183 // Data Access---------------------------------------------------------------
00184 
00185 // == INPUT/OUTPUT ==
00186 
00187 //: Write matches in ASCII to stream.
00188 void PairMatchSet::write_ascii(vcl_ostream& s) const
00189 {
00190   for (unsigned i = 0; i < matches_.size(); ++i) {
00191     int to_index = matches_[i];
00192     if (to_index != NoMatch)
00193       s << i << ' ' << to_index << vcl_endl;
00194   }
00195 }
00196 
00197 vcl_ostream& operator<<(vcl_ostream& s, const PairMatchSet& cc)
00198 {
00199   cc.write_ascii(s);
00200   return s;
00201 }
00202 
00203 bool PairMatchSet::read_ascii(vcl_istream& s)
00204 {
00205   clear();
00206   for (;;) {
00207     // Read 2 ints
00208     int i1, i2;
00209     s >> i1 >> i2;
00210     // Break if that failed
00211     if (!s.good())
00212       break;
00213     // Eat any whitespace
00214     s >> vcl_ws;
00215 
00216     // Sanity check
00217     if (i1 < 0 || i2 < 0 || i1 >= (int)matches_.size()) {
00218       vcl_cerr << "PairMatchSet::read_ascii -- Pair " << i1 << '-' << i2 << " is outside the valid range.\n";
00219       clear();
00220       return false;
00221     }
00222 
00223     // More sanity checking
00224     if (matches_[i1] != NoMatch) {
00225       vcl_cerr << "PairMatchSet::read_ascii() -- Warning:\n"
00226                << "Duplicate matches for " << i1 << ": " << matches_[i1] << " and " << i2 << vcl_endl;
00227       return false;
00228     }
00229 
00230     matches_[i1] = i2;
00231   }
00232 
00233   return compute_match_count() > 0;
00234 }
00235 
00236 vcl_istream& operator>>(vcl_istream& s, PairMatchSet& cc)
00237 {
00238   cc.read_ascii(s);
00239   return s;
00240 }
00241 
00242 //: Summarize matches on stream
00243 void PairMatchSet::print_brief(vcl_ostream& s) const
00244 {
00245   s << "PairMatchSet: ";
00246   for (unsigned i = 0; i < matches_.size(); i++)
00247     s << matches_[i] << ' ';
00248   s << vcl_endl;
00249 }
00250 
00251 //: Summarize matches on cout.
00252 void PairMatchSet::print_brief() const
00253 {
00254   unsigned n = matches_.size();
00255   char const *c = "";
00256   if (n > 30) {
00257     n = 30;
00258     c = "...";
00259   }
00260 
00261   for (unsigned i = 0; i < n; ++i)
00262     if (matches_[i] != NoMatch)
00263       vcl_cout << ' ' << matches_[i];
00264   vcl_cout << c << vcl_endl;
00265 }
00266 
00267 // Data Control--------------------------------------------------------------
00268 // -----------------------------------------------------------------------------
00269 
00270 
00271 // == ITERATOR [class PairMatchSet::iterator] ==
00272 
00273 //: Construct an empty iterator.
00274 PairMatchSet::iterator::iterator(bool full_only):
00275   c_(0),
00276   match_index_(0),
00277   full_only_(full_only)
00278 {
00279 }
00280 
00281 //: Construct an iterator which will enumerate the matches in PairMatchSet cc.
00282 PairMatchSet::iterator::iterator(const PairMatchSet& cc, bool full_only):
00283   c_(&cc),
00284   match_index_(0),
00285   full_only_(full_only)
00286 {
00287   match_index_ = -1;
00288   next();
00289 }
00290 
00291 //: Set an iterator to enumerate the matches in PairMatchSet cc.
00292 PairMatchSet::iterator& PairMatchSet::iterator::operator =(const PairMatchSet& cc)
00293 {
00294   c_ = &cc;
00295   match_index_ = -1;
00296   next();
00297   return *this;
00298 }
00299 
00300 //: Advance the iterator, returning false if all matches have been enumerated.
00301 bool PairMatchSet::iterator::next()
00302 {
00303   if (full_only_) {
00304     while (c_->get_match(++match_index_, &i1, &i2))
00305       if (isfull())
00306         return true;
00307     return false;
00308   }
00309   return c_->get_match(++match_index_, &i1, &i2);
00310 }
00311 
00312 #if 0 // insert these here for documentation purposes
00313 //: Return the first component of the match currently "pointed to" by the match iterator.
00314 int PairMatchSet::iterator::get_i1() const
00315 {
00316   return i1;
00317 }
00318 
00319 //: Return the second component of the match currently "pointed to" by the match iterator.
00320 int PairMatchSet::iterator::get_i2() const
00321 {
00322   return i2;
00323 }
00324 #endif
00325 
00326 //: Return true if neither of the indices of the match pointed to by the iterator is NoMatch.
00327 //  [Users should not need this]
00328 bool PairMatchSet::iterator::isfull() const
00329 {
00330   return i1 != NoMatch && i2 != NoMatch;
00331 }