00001 #ifndef GRIDDER_H
00002 #define GRIDDER_H
00003
00004 #include <algorithm>
00005 #include <iterator>
00006 #include <vector>
00007
00008 #include "Segment.h"
00009
00010 namespace AprilTags {
00011
00012
00013 template <class T>
00014 class Gridder {
00015 private:
00016 Gridder(const Gridder&);
00017 Gridder& operator=(const Gridder&);
00018
00019 struct Cell {
00020 T* object;
00021 Cell *next;
00022
00023 Cell() : object(NULL), next(NULL) {}
00024
00025 Cell(const Cell& c) : object(c.object), next(c.next) {}
00026
00027
00028 ~Cell() {
00029 delete next;
00030 }
00031
00032 Cell& operator=(const Cell &other) {
00033 if (this == &other)
00034 return *this;
00035
00036 object = other.object;
00037 next = other.next;
00038 return *this;
00039 }
00040 };
00041
00042
00043 void gridderInit(float x0Arg, float y0Arg, float x1Arg, float y1Arg, float ppCell) {
00044 width = (int) ((x1Arg - x0Arg)/ppCell + 1);
00045 height = (int) ((y1Arg - y0Arg)/ppCell + 1);
00046
00047 x1 = x0Arg + ppCell*width;
00048 y1 = y0Arg + ppCell*height;
00049 cells = std::vector< std::vector<Cell*> >(height, std::vector<Cell*>(width,(Cell*)NULL));
00050 }
00051
00052 float x0,y0,x1,y1;
00053 int width, height;
00054 float pixelsPerCell;
00055 std::vector< std::vector<Cell*> > cells;
00056
00057 public:
00058 Gridder(float x0Arg, float y0Arg, float x1Arg, float y1Arg, float ppCell)
00059 : x0(x0Arg), y0(y0Arg), x1(), y1(), width(), height(), pixelsPerCell(ppCell),
00060 cells() { gridderInit(x0Arg, y0Arg, x1Arg, y1Arg, ppCell); }
00061
00062
00063 ~Gridder() {
00064 for (unsigned int i = 0; i < cells.size(); i++) {
00065 for (unsigned int j = 0; j < cells[i].size(); j++)
00066 delete cells[i][j];
00067 }
00068 }
00069
00070 void add(float x, float y, T* object) {
00071 int ix = (int) ((x - x0)/pixelsPerCell);
00072 int iy = (int) ((y - y0)/pixelsPerCell);
00073
00074 if (ix>=0 && iy>=0 && ix<width && iy<height) {
00075 Cell *c = new Cell;
00076 c->object = object;
00077 c->next = cells[iy][ix];
00078 cells[iy][ix] = c;
00079
00080 }
00081 }
00082
00083
00084
00085
00086
00087 class Iterator {
00088 public:
00089 Iterator(Gridder* grid, float x, float y, float range)
00090 : outer(grid), ix0(), ix1(), iy0(), iy1(), ix(), iy(), c(NULL) { iteratorInit(x,y,range); }
00091
00092 Iterator(const Iterator& it)
00093 : outer(it.outer), ix0(it.ix0), ix1(it.ix1), iy0(it.iy0), iy1(it.iy1), ix(it.ix), iy(it.iy), c(it.c) {}
00094
00095 Iterator& operator=(const Iterator& it) {
00096 outer = it.outer;
00097 ix0 = it.ix0;
00098 ix1 = it.ix1;
00099 iy0 = it.iy0;
00100 iy1 = it.iy1;
00101 ix = it.ix;
00102 iy = it.iy;
00103 c = it.c;
00104 }
00105
00106 bool hasNext() {
00107 if (c == NULL)
00108 findNext();
00109 return (c != NULL);
00110 }
00111
00112 T& next() {
00113 T* thisObj = c->object;
00114 findNext();
00115 return *thisObj;
00116 }
00117
00118 private:
00119 void findNext() {
00120 if (c != NULL)
00121 c = c->next;
00122 if (c != NULL)
00123 return;
00124
00125 ix++;
00126 while (true) {
00127 if (ix > ix1) {
00128 iy++;
00129 ix = ix0;
00130 }
00131 if (iy > iy1)
00132 break;
00133
00134 c = outer->cells[iy][ix];
00135
00136 if (c != NULL)
00137 break;
00138 ix++;
00139 }
00140 }
00141
00142
00143 void iteratorInit(float x, float y, float range) {
00144 ix0 = (int) ((x - range - outer->x0)/outer->pixelsPerCell);
00145 iy0 = (int) ((y - range - outer->y0)/outer->pixelsPerCell);
00146
00147 ix1 = (int) ((x + range - outer->x0)/outer->pixelsPerCell);
00148 iy1 = (int) ((y + range - outer->y0)/outer->pixelsPerCell);
00149
00150 ix0 = std::max(0, ix0);
00151 ix0 = std::min(outer->width-1, ix0);
00152
00153 ix1 = std::max(0, ix1);
00154 ix1 = std::min(outer->width-1, ix1);
00155
00156 iy0 = std::max(0, iy0);
00157 iy0 = std::min(outer->height-1, iy0);
00158
00159 iy1 = std::max(0, iy1);
00160 iy1 = std::min(outer->height-1, iy1);
00161
00162 ix = ix0;
00163 iy = iy0;
00164
00165 c = outer->cells[iy][ix];
00166 }
00167
00168 Gridder* outer;
00169 int ix0, ix1, iy0, iy1;
00170 int ix, iy;
00171 Cell *c;
00172 };
00173
00174 typedef Iterator iterator;
00175 iterator find(float x, float y, float range) { return Iterator(this,x,y,range); }
00176 };
00177
00178 }
00179
00180 #endif