contrib/oxl/mvl/ClosestImagePointFinder.cxx
Go to the documentation of this file.
00001 // This is oxl/mvl/ClosestImagePointFinder.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 //:
00006 //  \file
00007 
00008 #include "ClosestImagePointFinder.h"
00009 #include <vcl_vector.h>
00010 #include <vcl_map.h>
00011 #include <vcl_functional.h>
00012 #include <vcl_utility.h>
00013 
00014 #include <vgl/vgl_box_2d.h>
00015 #include <vgl/vgl_homg_point_2d.h>
00016 #include <vnl/vnl_math.h>
00017 
00018 #include <mvl/HomgInterestPointSet.h>
00019 
00020 class vcl_multimap_double_int : public vcl_multimap<double, int, vcl_less <double> >
00021 {
00022   typedef vcl_multimap<double, int, vcl_less <double> > base;
00023  public:
00024   iterator insert(double key, int value);
00025   void clear();
00026 };
00027 
00028 vcl_multimap_double_int::iterator vcl_multimap_double_int::insert(double key, int value)
00029 {
00030   //vcl_cerr << " ins \t" << value << '\t' << key << vcl_endl;
00031   return base::insert(vcl_pair<const double, int>(key, value));
00032 }
00033 
00034 void vcl_multimap_double_int::clear() { base::erase(begin(), end()); }
00035 
00036 
00037 //: Initialize to allow fast lookups of corners in the given set.
00038 ClosestImagePointFinder::ClosestImagePointFinder(const HomgInterestPointSet& corners):
00039   px_(corners.size()),
00040   py_(corners.size())
00041 {
00042   // Make a map of image2 y value to corner2
00043   y2i_ = new vcl_multimap_double_int;
00044   for (unsigned i = 0; i < corners.size(); ++i) {
00045     double x = corners.get_2d(i)[0];
00046     double y = corners.get_2d(i)[1];
00047     px_[i] = x;
00048     py_[i] = y;
00049     y2i_->insert(y, i);
00050   }
00051 }
00052 
00053 //: Initialize to allow fast lookups of corners in the given set.
00054 ClosestImagePointFinder::ClosestImagePointFinder(vcl_vector<vgl_homg_point_2d<double> > const& corners)
00055  : px_(corners.size()), py_(corners.size())
00056 {
00057   y2i_ = new vcl_multimap_double_int;
00058   for (unsigned i = 0; i < corners.size(); ++i)
00059   {
00060     px_[i] = corners[i].x();
00061     py_[i] = corners[i].y();
00062     y2i_->insert(py_[i], i);
00063   }
00064 }
00065 
00066 ClosestImagePointFinder::~ClosestImagePointFinder()
00067 {
00068   delete y2i_;
00069 }
00070 
00071 void ClosestImagePointFinder::get_all_within_search_region(double cx, double cy, double w, double h, vcl_vector<int>* out)
00072 {
00073   get_all_within_search_region(vgl_box_2d<double>(cx - w, cx + w, cy - h, cy + h), out);
00074 }
00075 
00076 void ClosestImagePointFinder::get_all_within_search_region(vgl_box_2d<double> const& disparity_bounds, vcl_vector<int>* out)
00077 {
00078   // Look at `point2's between y0 and y1
00079   vcl_multimap_double_int::iterator potential = y2i_->lower_bound(disparity_bounds.min_y());
00080   vcl_multimap_double_int::iterator end =       y2i_->upper_bound(disparity_bounds.max_y() + 1);
00081 #if 0
00082   vcl_cerr << "map:";
00083   for (vcl_multimap_double_int::iterator p = y2i_->begin(); p != y2i_->end(); ++p)
00084     vcl_cerr << ' '<< (*p).second << '[' << (*p).first << ']';
00085   vcl_cerr << vcl_endl;
00086 #endif // 0
00087   out->erase(out->begin(), out->end());
00088   for (; potential != end; ++potential) {
00089     int point2_index = (*potential).second;
00090     if (disparity_bounds.contains(px_[point2_index], py_[point2_index]))
00091       out->push_back(point2_index);
00092   }
00093 }
00094 
00095 //: Returns number that were within range.
00096 int ClosestImagePointFinder::get_closest_within_region(double cx, double cy, double w, double h, int* out, double mindist_sq)
00097 {
00098   // setup_checklist_disparity
00099   vgl_box_2d<double> disparity_bounds(cx - w, cx + w, cy - h, cy + h);
00100 
00101   // Look at `point2's between y0 and y1
00102   vcl_multimap_double_int::iterator potential = y2i_->lower_bound(disparity_bounds.min_y());
00103   vcl_multimap_double_int::iterator end =       y2i_->upper_bound(disparity_bounds.max_y() + 1);
00104 
00105   double orig_mindist_sq = mindist_sq;
00106 
00107   last_index_ = -1;
00108   int inrange = 0;
00109   for (; potential != end; ++potential) {
00110     int point2_index = (*potential).second;
00111     double x = px_[point2_index];
00112     double y = py_[point2_index];
00113     if (disparity_bounds.contains(x, y)) {
00114       double dx = x - cx;
00115       double dy = y - cy;
00116       double d2 = dx*dx + dy*dy;
00117       if (d2 < orig_mindist_sq)
00118         ++inrange;
00119       if (d2 < mindist_sq) {
00120         mindist_sq = d2;
00121         last_index_ = point2_index;
00122       }
00123     }
00124   }
00125   last_d2_ = mindist_sq;
00126   last_inrange_ = inrange;
00127   if (out)
00128     *out = last_index_;
00129 
00130   return inrange;
00131 }
00132 
00133 int ClosestImagePointFinder::get_closest_within_region(double cx, double cy, double w, double h, int* out)
00134 {
00135   double d = vnl_math_max(w,h);
00136   return get_closest_within_region(cx, cy, w, h, out, d*d);
00137 }
00138 
00139 //: Returns number that were within range.
00140 int ClosestImagePointFinder::get_closest_within_distance(double cx, double cy, double r, int* out)
00141 {
00142   return get_closest_within_region(cx, cy, r*2, r*2, out, r*r);
00143 }