contrib/oxl/mvl/TripleMatchSet.cxx
Go to the documentation of this file.
00001 // This is oxl/mvl/TripleMatchSet.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 //:
00006 // \file
00007 
00008 #include "TripleMatchSet.h"
00009 //
00010 #include <vcl_cstdlib.h> // for vcl_abort()
00011 #include <vcl_iostream.h>
00012 #include <vnl/vnl_matrix.h>
00013 #include <mvl/PairMatchSet.h>
00014 
00015 //: Initialize a TripleMatchSet from a pair of PairMatchSets.
00016 // The PairMatchSets are adopted by the TripleMatchSet, which will
00017 // delete them.
00018 TripleMatchSet::TripleMatchSet(PairMatchSet* match12, PairMatchSet* match23)
00019 {
00020   match12_ = match12;
00021   match23_ = match23;
00022 }
00023 
00024 //: Initialize a TripleMatchSet, by specifying the maximum i1, i2, i3 values.
00025 // Keep these conservative, as arrays of that length will be made.  Currently
00026 // the i3 value is ignored.
00027 TripleMatchSet::TripleMatchSet(int i1_max, int i2_max, int)
00028 {
00029   match12_ = new PairMatchSet(i1_max);
00030   match23_ = new PairMatchSet(i2_max);
00031 }
00032 
00033 //: Delete the PairMatchSets
00034 TripleMatchSet::~TripleMatchSet()
00035 {
00036   delete match12_;
00037   delete match23_;
00038 }
00039 
00040 //: Destroy current PairMatchSets and adopt two new ones.
00041 void TripleMatchSet::set(PairMatchSet* match12, PairMatchSet* match23)
00042 {
00043   delete match12_;
00044   delete match23_;
00045   match12_ = match12;
00046   match23_ = match23;
00047 }
00048 
00049 //: Join two PairMatchSets on their 2nd and 1st columns respectively.
00050 // I.e. make the TripleMatchSet which contains (i1,i2,i3) iff
00051 //
00052 // matches12.contains(i1, i2) and matches23.contains(i2, i3)
00053 //
00054 void TripleMatchSet::set_from_pairwise_matches(const PairMatchSet& matches12,
00055                                                const PairMatchSet& matches23)
00056 {
00057   clear_matches();
00058   for (PairMatchSet::iterator p12 = matches12; p12; p12.next()) {
00059     int i3 = matches23.get_match_12(p12.get_i2());
00060     if (matchp(i3))
00061       add_match(p12.get_i1(), p12.get_i2(), i3);
00062   }
00063   vcl_cerr << "TripleMatchSet: " << count() << " triplet matches.\n";
00064 }
00065 
00066 //: Write as three ascii columns.
00067 void TripleMatchSet::write_ascii(vcl_ostream & s) const
00068 {
00069   for (iterator match = begin(); match; ++match) {
00070     s << match.get_i1() << '\t'
00071       << match.get_i2() << '\t'
00072       << match.get_i3() << '\n';
00073   }
00074 }
00075 
00076 //: Read from ascii vcl_istream
00077 bool TripleMatchSet::read_ascii(vcl_istream& s)
00078 {
00079   vnl_matrix<double> m;
00080   s >> m;
00081   if (!s.good() && !s.eof())
00082     return false;
00083 
00084   if (m.columns() != 3) {
00085     vcl_cerr << "TripleMatchSet::read_ascii(): cols = " << m.columns() << ", not 3\n";
00086     return false;
00087   }
00088 
00089   int n = m.rows();
00090 
00091   int i1_max = 0;
00092   int i2_max = 0;
00093   for (int i = 0; i < n; ++i) {
00094     if (m(i,0) > i1_max) i1_max = (int)m(i,0);
00095     if (m(i,1) > i2_max) i2_max = (int)m(i,2);
00096   }
00097 
00098   clear_matches();
00099   // set(new PairMatchSet(i1_max+1), new PairMatchSet(i2_max+1));
00100 
00101   {
00102     for (int i = 0; i < n; ++i)
00103       add_match(int(m(i,0)), int(m(i,1)), int(m(i,2)));
00104   }
00105 
00106   return true;
00107 }
00108 
00109 //: Write to vcl_ostream with header
00110 vcl_ostream& operator << (vcl_ostream& s, const TripleMatchSet& matches)
00111 {
00112   s << "# TripleMatchSet: " << matches.count() << " triplet matches.\n";
00113   matches.write_ascii(s);
00114   return s;
00115 }
00116 
00117 vcl_istream& operator >> (vcl_istream& s, TripleMatchSet& matches)
00118 {
00119   matches.read_ascii(s);
00120   return s;
00121 }
00122 
00123 // == TRIPLET ACCESS ==
00124 
00125 //: Add triplet (i1, i2, i3) to the matchset.
00126 //  Any existing matches of the form (i1, *, *) are removed. O(1).
00127 bool TripleMatchSet::add_match(int i1, int i2, int i3)
00128 {
00129   if (get_match_23(i2) != MatchSet::NoMatch) {
00130     vcl_cerr << "TripleMatchSet::add_match(" <<i1<< ", "<<i2<<", "<<i3<<")\n";
00131     int old_i1 = get_match_21(i2);
00132     int old_i3 = get_match_23(i2);
00133     vcl_cerr<<"*** i2 is already in a match ("<<old_i1<<'/'<<i2<<'/'<<old_i3<<")\n";
00134   }
00135 
00136   if (get_match_12(i1) != MatchSet::NoMatch) {
00137     vcl_cerr<<"TripleMatchSet::add_match("<<i1<<", "<<i2<<", "<<i3<<")\n";
00138     int old_i2 = get_match_12(i1);
00139     int old_i3 = get_match_23(old_i2);
00140     vcl_cerr<<"*** i1 is already in a match ("<<i1<<'/'<<old_i2<<'/'<<old_i3<<")\n";
00141   }
00142 
00143   return match12_->add_match(i1, i2) && match23_->add_match(i2, i3);
00144 }
00145 
00146 //: Return the number of triplets. O(n).
00147 int TripleMatchSet::count() const
00148 {
00149   int c = 0;
00150   for (iterator match = begin(); match; match.next())
00151     ++c;
00152   return c;
00153 }
00154 
00155 //: Remove all tuples.
00156 void TripleMatchSet::clear_matches()
00157 {
00158   match12_->clear();
00159   match23_->clear();
00160 }
00161 
00162 //-----------------------------------------------------------------------------
00163 //: Select(1 = i1).2, meaning take the 2nd component of the tuples in which the first component equals i1.
00164 // Complexity O(1).
00165 int TripleMatchSet::get_match_12(int i1) const
00166 {
00167   return match12_->get_match_12(i1);
00168 }
00169 
00170 //: Select(1 = i1).3
00171 // Complexity O(1)
00172 int TripleMatchSet::get_match_13(int i1) const
00173 {
00174   return get_match_23(get_match_12(i1));
00175 }
00176 
00177 //: Select(2 = i2).3 Complexity O(1)
00178 int TripleMatchSet::get_match_23(int i2) const
00179 {
00180   return match23_->get_match_12(i2);
00181 }
00182 
00183 //: Select(2 = i2).1 Complexity O(n)
00184 int TripleMatchSet::get_match_21(int i2) const
00185 {
00186   return match12_->get_match_21(i2);
00187 }
00188 
00189 //: Select(3 = i3).1 Complexity O(n)
00190 int TripleMatchSet::get_match_31(int i3) const
00191 {
00192   return get_match_21(get_match_32(i3));
00193 }
00194 
00195 //: Select(3 = i3).2 Complexity O(n)
00196 int TripleMatchSet::get_match_32(int i3) const
00197 {
00198   return match23_->get_match_21(i3);
00199 }
00200 
00201 //: Select({1,2} = {i1, i2}).3
00202 // Complexity O(1).
00203 int TripleMatchSet::get_match_123(int i1, int i2) const
00204 {
00205   int ii = match12_->get_match_12(i1);
00206   if (ii != i2)
00207     return MatchSet::NoMatch;
00208   else
00209     return get_match_23(i2);
00210 }
00211 
00212 //: Select(1 = c).{1,2,3}
00213 //  Complexity O(1).  Returns true iff a match was found.
00214 bool TripleMatchSet::get_1(int c, int* i1, int* i2, int* i3) const
00215 {
00216   if (c >= match12_->size())
00217     return false;
00218 
00219   *i1 = c;
00220   *i2 = match12_->get_match_12(*i1);
00221   *i3 = match23_->get_match_12(*i2);
00222 
00223   return true;
00224 }
00225 
00226 //: Select(2 = c).{1,2,3}  Complexity O(n).
00227 bool TripleMatchSet::get_2(int c, int* i1, int* i2, int* i3) const
00228 {
00229   return get_1(get_match_21(c), i1, i2, i3);
00230 }
00231 
00232 //: Select(3 = c).{1,2,3}  Complexity O(n).
00233 bool TripleMatchSet::get_3(int c, int* i1, int* i2, int* i3) const
00234 {
00235   return get_1(get_match_31(c), i1, i2, i3);
00236 }
00237 
00238 // -----------------------------------------------------------------------------
00239 
00240 // == DEVELOPER INFORMATION ==
00241 
00242 // - An implementation detail.  If the underlying PairMatchSets
00243 // have been modified, there may be i2-i3 matches that have no corresponding
00244 // i1-i2. This routine clears them (noisily).
00245 void TripleMatchSet::clear_nontriplets()
00246 {
00247   //mt_clear_affinity_nontriplets (match12_->get_table(), match23_->get_table());
00248   vcl_vector<bool> accept(match23_->size());
00249   for (vcl_vector<bool>::iterator i=accept.begin(); i!=accept.end(); ++i)
00250     *i = false;
00251 
00252   int cleared_count = 0;
00253   for (int i1 = 0; i1 < match12_->size(); i1++) {
00254     int i2 = match12_->get_match_12(i1);
00255     if (i2 != NoMatch) {
00256       int i3 = NoMatch;
00257       if (i2 >= match23_->size() || i2 < 0)
00258         vcl_cerr << "TripleMatchSet::clear_nontriplets() -- bad i2 = " << i2 << vcl_endl;
00259       else
00260         i3 = match23_->get_match_12(i2);
00261 
00262       if (i3 == NoMatch) {
00263         match12_->add_match(i1, NoMatch);
00264         ++cleared_count;
00265       }
00266       else
00267         accept[i2] = true;
00268     }
00269   }
00270   vcl_cerr << "TripleMatchSet::clear_nontriplets() -- Cleared i2 " << cleared_count << vcl_endl;
00271 
00272   for (int i2 = 0; i2 < match23_->size(); i2++)
00273     if (!accept[i2]) {
00274       match23_->add_match(i2, NoMatch);
00275       ++cleared_count;
00276     }
00277 
00278   vcl_cerr << "TripleMatchSet::clear_nontriplets() -- Cleared i3 " << cleared_count << vcl_endl;
00279 }
00280 
00281 bool TripleMatchSet::delete_match(int i1, int i2, int i3)
00282 {
00283   int old_12 = match12_->get_match_12(i1);
00284   if (old_12 != i2) {
00285     vcl_cerr << "TripleMatchSet::delete_match - old/new i2 = " << old_12 << '/' << i2 << vcl_endl;
00286     match23_->clear_match_1(old_12);
00287   }
00288   int old_23 = match23_->get_match_12(i2);
00289   if (old_23 != i3) {
00290     vcl_cerr << "TripleMatchSet::delete_match - old/new i3 = " << old_23 << '/' << i3 << vcl_endl;
00291   }
00292 
00293   match12_->clear_match_1(i1);
00294   match23_->clear_match_1(i2);
00295 
00296   return true;
00297 }
00298 
00299 // - Return the maximum allowed value of i1.
00300 int TripleMatchSet::size() const
00301 {
00302   return match12_->size();
00303 }
00304 
00305 // - Call PairMatchSets update_feature_match_data
00306 void TripleMatchSet::update_feature_match_data()
00307 {
00308   match12_->update_feature_match_data();
00309   match23_->update_feature_match_data();
00310 }
00311 
00312 
00313 // -----------------------------------------------------------------------------
00314 
00315 #if 0
00316 TripleMatchSet::iterator::iterator(bool)
00317 {
00318   vcl_abort();
00319 }
00320 #endif
00321 
00322 //: Construct an iterator that points to the first triplet of "ccc".
00323 // The full_only flag is of interest only to developers.
00324 TripleMatchSet::iterator::iterator(const TripleMatchSet& ccc, bool full_only):
00325   c_(&ccc),
00326   match_index_(0),
00327   full_only_(full_only)
00328 {
00329   match_index_ = -1;
00330   next();
00331 }
00332 
00333 //: Advance to point to the next triplet.
00334 bool TripleMatchSet::iterator::next()
00335 {
00336   if (full_only_) {
00337     while (c_->get_match(++match_index_, &i1, &i2, &i3))
00338       if (isfull())
00339         return true;
00340     return false;
00341   }
00342   return c_->get_match(++match_index_, &i1, &i2, &i3);
00343 }
00344 
00345 //: Return true if there are still unseen matches
00346 TripleMatchSet::iterator::operator bool () const
00347 {
00348   return match_index_ < c_->size();
00349 }
00350 
00351 //: Return true if the current "pointed-to" match is a proper triplet.
00352 // Should never return false in normal use.
00353 bool TripleMatchSet::iterator::isfull() const
00354 {
00355   return i1 != NoMatch && i2 != NoMatch && i3 != NoMatch;
00356 }
00357 
00358 
00359 #if 0
00360 MA_MATCH_TABLE_STR* TripleMatchSet::make_matchtable()
00361 {
00362   return mt_3image_affinity_to_match (match12_->get_table(), match23_->get_table());
00363 }
00364 
00365 MA_MATCH_TABLE_STR* TripleMatchSet::make_matchtable_12()
00366 {
00367   //return mt_3image_affinity123_to_match23 (match12_->get_table(), match23_->get_table());
00368   // In fact this is used instead in vi_3image_match_feature:
00369   return mt_3image_affinity_to_match (match12_->get_table(), match23_->get_table());
00370 }
00371 
00372 MA_MATCH_TABLE_STR* TripleMatchSet::make_matchtable_23()
00373 {
00374   return mt_3image_affinity123_to_match23 (match12_->get_table(), match23_->get_table());
00375 }
00376 
00377 void TripleMatchSet::update_from(MA_MATCH_TABLE_STR* matchtable)
00378 {
00379   mt_3image_match_to_affinity (matchtable, match12_->get_table(), match23_->get_table());
00380 }
00381 #endif
00382