00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include <limits>
00034 #include <iterator>
00035 #include <map>
00036 #include <more/gen/iterator.h>
00037 #include <more/gen/view.h>
00038 #include <more/gen/utility.h>
00039 #include <more/math/math.h>
00040 #include <more/num/vectin.h>
00041
00042 #ifndef MORE_POINT_MAP_H
00043 #define MORE_POINT_MAP_H
00044
00045
00046 namespace more {
00047 namespace num {
00048
00049 #ifdef CXX_HAVE_LONG_LONG
00050 typedef unsigned long long pindex_type;
00051 #else
00052 typedef unsigned long pindex_type;
00053 #endif
00054
00055 template<typename T, int D>
00056 inline pindex_type
00057 fold(more::vectin<T, D> const& x) {
00058 const double scale = ldexp(.49, 8*sizeof(pindex_type)/D);
00059
00060
00061 pindex_type res = 0;
00062 for (int i = 0; i < D; ++i)
00063 res |= more::bitpow((pindex_type)((1.0+x[i])*scale), D) << i;
00064 return res;
00065 }
00066
00067 template< typename Position, typename Data,
00068 typename Metric = euclidian_metric<Position> >
00069 struct point_map {
00070
00071
00072 typedef Position position_type;
00073 typedef Position key_type;
00074 typedef Metric metric_function;
00075 typedef typename metric_function::result_type metric_type;
00076 static const int ndim = Position::CTC_size;
00077 typedef more::pindex_type pindex_type;
00078 typedef Data data_type;
00079 typedef std::pair<Position, Data> value_type;
00080 #if !defined(MORE_BACKWARD) || MORE_BACKWARD >= 20000601
00081 private:
00082 #endif
00083 typedef std::map<pindex_type, value_type> container;
00084 typedef typename container::iterator full_iterator;
00085 typedef typename container::const_iterator full_const_iterator;
00086 typedef typename container::value_type full_value_type;
00087 public:
00088
00089 struct vicinity_filter
00090 : std::unary_function<full_value_type, bool> {
00091 vicinity_filter() {}
00092 vicinity_filter(position_type const& x_, metric_type d_,
00093 metric_function const& met)
00094 : x(x_), d(d_), metric(met) {}
00095 vicinity_filter(vicinity_filter const& flt)
00096 : x(flt.x), d(flt.d), metric(flt.metric) {}
00097
00098 bool operator()(full_value_type const& v) {
00099 return metric(v.second.first, x) <= d;
00100 }
00101
00102 private:
00103 position_type x;
00104 metric_type d;
00105 metric_function metric;
00106 };
00107
00108 typedef gen::transform_if_view< full_iterator, vicinity_filter,
00109 gen::select2nd<full_value_type> >
00110 vicinity_view;
00111 typedef gen::transforming_iterator< full_iterator,
00112 gen::select2nd<full_value_type> >
00113 iterator;
00114 typedef gen::transforming_iterator
00115 < full_const_iterator,
00116 gen::select2nd<const full_value_type> >
00117 const_iterator;
00118
00119 point_map()
00120 : scale(1.0), trunc_cnt(0) {}
00121 point_map(metric_type radius_max)
00122 : scale(1.0/radius_max), trunc_cnt(0) {}
00123
00124 #if defined (MORE_BACKWARD) && MORE_BACKWARD < 20000601
00125 void insert(position_type const& x, data_type const& y) {
00126 position_type z = scale_and_truncate(x);
00127 c.insert(full_value_type(fold(z), value_type(x, y)));
00128 }
00129 #endif
00130 void insert(value_type const& x) {
00131 position_type z = scale_and_truncate(x.first);
00132 c.insert(full_value_type(fold(z), x));
00133 }
00134 #if defined (MORE_BACKWARD) && MORE_BACKWARD < 20000601
00135 void insert(full_iterator hint,
00136 position_type const& x, data_type const& y) {
00137 position_type z = scale_and_truncate(x);
00138 c.insert(hint, full_value_type(fold(z), value_type(x, y)));
00139 }
00140 #endif
00141 void insert(iterator hint, value_type const& x) {
00142 position_type z = scale_and_truncate(x);
00143 c.insert(hint.sub_iterator(), full_value_type(fold(z), x));
00144 }
00145
00146 vicinity_view vicinity(position_type const& x, metric_type d);
00147 iterator find_closest(position_type const& x);
00148
00149 const_iterator begin() const { return const_iterator(c.begin()); }
00150 const_iterator end() const { return const_iterator(c.end()); }
00151 iterator begin() { return iterator(c.begin()); }
00152 iterator end() { return iterator(c.end()); }
00153
00154 void clear() { c.clear(); trunc_cnt = 0; scale = 1.0; }
00155
00156 private:
00157 position_type
00158 scale_and_truncate(position_type x) {
00159 for (int i = 0; i < ndim; ++i) {
00160 x[i] *= scale;
00161 if (x[i] < -1.0) { ++trunc_cnt; x[i] = -1.0; }
00162 else if (x[i] > 1.0) { ++trunc_cnt; x[i] = 1.0; }
00163 }
00164 return x;
00165 }
00166 void corner_indices(position_type const&, metric_type,
00167 pindex_type&, pindex_type&);
00168
00169 metric_type scale;
00170 int trunc_cnt;
00171 container c;
00172 metric_function metric;
00173 };
00174
00175
00176 template<typename T, typename U, typename Metric>
00177 inline void
00178 point_map<T, U, Metric>
00179 ::corner_indices(position_type const& x, metric_type d,
00180 pindex_type& idx_inf, pindex_type& idx_sup) {
00181 position_type x_inf = x, x_sup = x;
00182 for (int i = 0; i < ndim; ++i) {
00183 x_inf[i] -= d;
00184 x_sup[i] += d;
00185 }
00186 position_type z_inf = scale*x_inf;
00187 position_type z_sup = scale*x_sup;
00188 for (int i = 0; i < ndim; ++i) {
00189 if (z_inf[i] < -1.0) {
00190 z_inf[i] = -1.0;
00191 if (z_sup[i] < -1.0) z_sup[i] = -1.0;
00192 }
00193 if (z_sup[i] > 1.0) {
00194 z_sup[i] = 1.0;
00195 if (z_inf[i] > 1.0) z_inf[i] = 1.0;
00196 }
00197 }
00198 idx_inf = more::max(fold(z_inf), c.begin()->first);
00199 full_iterator last = c.end(); --last;
00200 idx_sup = more::min(fold(z_sup), last->first);
00201 }
00202
00203 template<typename T, typename U, typename Metric>
00204 inline typename point_map<T, U, Metric>::vicinity_view
00205 point_map<T, U, Metric>
00206 ::vicinity(position_type const& x, metric_type d) {
00207 pindex_type idx_inf, idx_sup;
00208 corner_indices(x, d, idx_inf, idx_sup);
00209 full_iterator it_inf = c.lower_bound(idx_inf);
00210 if (it_inf != c.begin()) --it_inf;
00211 return vicinity_view(it_inf, c.upper_bound(idx_sup),
00212 vicinity_filter(x, d, metric));
00213 }
00214
00215 template<typename T, typename U, typename Metric>
00216 inline typename point_map<T, U, Metric>::iterator
00217 point_map<T, U, Metric>
00218 ::find_closest(position_type const& x) {
00219 if (c.size() < 2) {
00220 if (c.size() == 1) return iterator(c.begin());
00221 else throw std::logic_error
00222 ("point_map::find_closest in empty map.");
00223 }
00224 pindex_type idx = fold(scale_and_truncate(x));
00225 full_iterator it_inc = c.lower_bound(idx);
00226 full_iterator it_dec = it_inc;
00227 full_iterator it_min = it_inc;
00228 metric_type d_min = metric(it_min->second.first, x);
00229 pindex_type idx_inf, idx_sup;
00230 corner_indices(x, d_min, idx_inf, idx_sup);
00231
00232 bool changed;
00233 do {
00234 changed = 0;
00235 if (it_dec->first > idx_inf) {
00236 changed = true;
00237 --it_dec;
00238 metric_type d = metric(it_dec->second.first, x);
00239 if (d < d_min) {
00240 d_min = d;
00241 it_min = it_dec;
00242 corner_indices(x, d_min, idx_inf, idx_sup);
00243 }
00244 }
00245 if (it_inc->first < idx_sup) {
00246 changed = true;
00247 ++it_inc;
00248 metric_type d = metric(it_inc->second.first, x);
00249 if (d < d_min) {
00250 d_min = d;
00251 it_min = it_inc;
00252 corner_indices(x, d_min, idx_inf, idx_sup);
00253 }
00254 }
00255 }
00256 while (changed);
00257
00258 return iterator(it_min);
00259 }
00260 }}
00261 #endif