00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef BUCKET2D_H
00021 #define BUCKET2D_H
00022
00023 #include <assert.h>
00024 #include <math.h>
00025 #include <string.h>
00026 #include "mlist.h"
00027
00042 template <typename T>
00043 class bucket2d {
00044 public:
00045
00046 bucket2d() : buckets(0), nb_elem(0) {}
00047 bucket2d(unsigned width, unsigned height, unsigned size_bits):buckets(0),nb_elem(0) {setup(width,height,size_bits);}
00048 virtual ~bucket2d();
00049
00050 void setup(unsigned width, unsigned height, unsigned size_bits);
00051
00052 void add_pt(T *p) { assert(p); ++nb_elem; MLIST_INSERT(buckets[idx(p->u, p->v)], p, points_in_frame); }
00053
00054 void clear();
00055
00056 void rm_pt(T *p) { --nb_elem; MLIST_RM(&buckets[idx(p->u, p->v)], p, points_in_frame); }
00057
00058 void move_pt(T *p, float u, float v) {
00059 unsigned old_idx = idx(p->u,p->v);
00060 unsigned new_idx = idx(u,v);
00061 if (old_idx != new_idx) {
00062 MLIST_RM(&buckets[old_idx],p,points_in_frame);
00063 MLIST_INSERT(buckets[new_idx], p, points_in_frame);
00064 }
00065 p->u=u;
00066 p->v=v;
00067 }
00068
00069 class iterator {
00070 public:
00071 iterator(bucket2d &b, float u, float v, float r);
00072 iterator(bucket2d &b);
00073 void operator ++();
00074 T *operator *() { return it; }
00075 T *elem() { return it; }
00076 bool end() { return j>ve; }
00077
00078 protected:
00079 bucket2d *b;
00080
00081 unsigned cur_idx, ub, ue, vb, ve, i, j;
00082 T *it;
00083 void next();
00084 };
00085
00086 iterator search(float u, float v, float r) { return iterator(*this, u, v, r); }
00087 iterator begin() { return iterator(*this); }
00088 T *closest_point(float u, float v, float max_dist);
00089
00090 unsigned size() const { return nb_elem; }
00091
00092 protected:
00093 unsigned size_bits;
00094 unsigned buckets_max_u, buckets_max_v;
00095
00096 T **buckets;
00097 unsigned nb_elem;
00098
00099 unsigned idxu(unsigned u) {
00100 unsigned iu = u >> size_bits;
00101 if (iu>buckets_max_u) iu = buckets_max_u;
00102 return iu;
00103 }
00104 unsigned idxu(int u) { if (u<0) return 0; return idxu((unsigned)u); }
00105
00106 unsigned idxv(unsigned v) {
00107 unsigned iv = v >> size_bits;
00108 if (iv>buckets_max_v) iv = buckets_max_v;
00109 return iv;
00110 }
00111 unsigned idxv(int v) {
00112 if (v<0) return 0;
00113 return idxv((unsigned)v);
00114 }
00115 unsigned idx(unsigned u, unsigned v) { return idxv(v)*(buckets_max_u+1) + idxu(u); }
00116 unsigned idx(int u, int v) { return idxv(v)*(buckets_max_u+1) + idxu(u); }
00117 unsigned idx(float u, float v) { return idx((int)u, (int)v); }
00118
00119 };
00120
00121 template<typename T>
00122 bucket2d<T>::~bucket2d() {
00123 if (buckets) delete[] buckets;
00124 }
00125
00126 template<typename T>
00127 void bucket2d<T>::setup(unsigned width, unsigned height, unsigned size_bits)
00128 {
00129 this->size_bits = size_bits;
00130
00131 buckets_max_u = ((width + (1<<size_bits)-1) >> size_bits)-1;
00132 buckets_max_v = ((height + (1<<size_bits)-1) >> size_bits)-1;
00133
00134 assert(buckets_max_u>0 && buckets_max_v>0);
00135
00136 if (buckets) delete[] buckets;
00137 int n= (buckets_max_u+1)*(buckets_max_v+1);
00138 buckets = new T *[n];
00139 memset(buckets, 0, n*sizeof(T *));
00140 nb_elem = 0;
00141 }
00142
00143 template<typename T>
00144 void bucket2d<T>::clear() {
00145 if (!buckets) return;
00146
00147 int n= (buckets_max_u+1)*(buckets_max_v+1);
00148 memset(buckets, 0, n*sizeof(T *));
00149 nb_elem= 0;
00150 }
00151
00152 template<typename T>
00153 bucket2d<T>::iterator::iterator(bucket2d &bucket, float u, float v, float r)
00154 : b(&bucket)
00155 {
00156 ub = b->idxu((int)floorf(u-r));
00157 ue = b->idxu((int)ceilf(u+r));
00158 vb = b->idxv((int)floorf(v-r));
00159 ve = b->idxv((int)ceilf(v+r));
00160 i = ub;
00161 j = vb;
00162
00163 cur_idx = j*(b->buckets_max_u+1)+i;
00164 assert(cur_idx<(b->buckets_max_u+1)*(b->buckets_max_v+1));
00165 it = b->buckets[cur_idx];
00166 next();
00167 }
00168
00169 template<typename T>
00170 bucket2d<T>::iterator::iterator(bucket2d &bucket)
00171 : b(&bucket)
00172 {
00173 ub = 0;
00174 ue = b->buckets_max_u;
00175 vb = 0;
00176 ve = b->buckets_max_v;
00177 i = 0;
00178 j = 0;
00179
00180 cur_idx = 0;
00181 it = b->buckets[cur_idx];
00182 next();
00183 }
00184
00185 template<typename T>
00186 void bucket2d<T>::iterator::next() {
00187 while(it==0) {
00188 ++i;
00189 if (i>ue) {
00190 i = ub;
00191 ++j;
00192 if (j>ve) {
00193 cur_idx=0xffffffff;
00194 break;
00195 }
00196 }
00197 cur_idx = j*(b->buckets_max_u+1)+i;
00198 assert(cur_idx<(b->buckets_max_u+1)*(b->buckets_max_v+1));
00199 it = b->buckets[cur_idx];
00200 }
00201 }
00202
00203 template<typename T>
00204 void bucket2d<T>::iterator::operator ++() {
00205 it = it->points_in_frame.next;
00206 next();
00207 }
00208
00209 template <typename T>
00210 T *bucket2d<T>::closest_point(float u, float v, float max_dist)
00211 {
00212 float dist = max_dist*max_dist;
00213 T* best=0;
00214 for(iterator it = search(u,v,max_dist); !it.end(); ++it) {
00215 float du = u - it.elem()->u;
00216 du *= du;
00217 if (du>max_dist) continue;
00218 float dv = v - it.elem()->v;
00219 dv *= dv;
00220 float d = du+dv;
00221 if (d<dist) {
00222 dist = d;
00223 best = it.elem();
00224 }
00225 }
00226 return best;
00227 }
00228
00229 #endif