00001
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005
00006
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
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
00038 ClosestImagePointFinder::ClosestImagePointFinder(const HomgInterestPointSet& corners):
00039 px_(corners.size()),
00040 py_(corners.size())
00041 {
00042
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
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
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
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
00096 int ClosestImagePointFinder::get_closest_within_region(double cx, double cy, double w, double h, int* out, double mindist_sq)
00097 {
00098
00099 vgl_box_2d<double> disparity_bounds(cx - w, cx + w, cy - h, cy + h);
00100
00101
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
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 }