00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "gridkeeper.h"
00011
00012 static double d2(double x1, double x2, double y1, double y2)
00013 {
00014 return ((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
00015 }
00016
00017 GridHandler::GridHandler()
00018 {
00019 }
00020
00021 void GridHandler::handle(Event *e)
00022 {
00023 MoveEvent *me = (MoveEvent *)e;
00024 MobileNode **pptr;
00025 MobileNode * token_ = me->token_;
00026
00027 if ((pptr = me->leave_)) {
00028 while (*pptr) {
00029 if ((*pptr)->address() == token_->address()) break;
00030 pptr = &((*pptr)->next());
00031 }
00032 if (!(*pptr)) abort();
00033 else {
00034 *pptr = token_->next();
00035 token_->next() = 0;
00036 }
00037
00038 }
00039 if ((pptr = me->enter_)) {
00040 if (token_->next()) abort();
00041 token_->next() = *pptr;
00042 *pptr = token_;
00043 }
00044 delete me;
00045
00046
00047
00048
00049 }
00050
00051 GridKeeper* GridKeeper::instance_;
00052
00053 static class GridKeeperClass : public TclClass {
00054 public:
00055 GridKeeperClass() : TclClass("GridKeeper") {}
00056 TclObject* create(int, const char*const*) {
00057 return (new GridKeeper);
00058 }
00059 } class_grid_keeper;
00060
00061 GridKeeper::GridKeeper() : size_(0),grid_(NULL), dim_x_(0), dim_y_(0)
00062 {
00063 gh_ = new GridHandler();
00064 }
00065
00066 GridKeeper::~GridKeeper()
00067 {
00068 int i;
00069 for (i = 0; i <= dim_x_; i++) {
00070 delete [] grid_[i];
00071 }
00072 delete [] grid_;
00073 }
00074
00075 int GridKeeper::command(int argc, const char*const* argv)
00076 {
00077 int i, grid_x, grid_y;
00078 Tcl& tcl = Tcl::instance();
00079 MobileNode *mn;
00080
00081 if (argc == 2) {
00082 if (strcmp(argv[1], "dump") == 0) {
00083 dump();
00084 return (TCL_OK);
00085 }
00086 }
00087
00088 if (argc == 3) {
00089 if (strcmp(argv[1], "addnode") == 0) {
00090 mn = (MobileNode *)TclObject::lookup(argv[2]);
00091 grid_x = aligngrid((int)mn->X(), dim_x_);
00092 grid_y = aligngrid((int)mn->Y(), dim_y_);
00093 mn->next() = grid_[grid_x][grid_y];
00094 grid_[grid_x][grid_y] = mn;
00095 size_++;
00096 return (TCL_OK);
00097 }
00098 }
00099 if (argc == 4 && strcmp(argv[1], "dimension") == 0) {
00100 if (instance_ == 0) instance_ = this;
00101
00102 dim_x_ = strtol(argv[2], (char**)0, 0);
00103 dim_y_ = strtol(argv[3], (char**)0, 0);
00104
00105 if (dim_x_ <= 0 || dim_y_ <= 0) {
00106 tcl.result("illegal grid dimension");
00107 return (TCL_ERROR);
00108 }
00109
00110 grid_ = new MobileNode **[dim_x_];
00111 for (i = 0; i < dim_x_; i++) {
00112 grid_[i] = new MobileNode *[dim_y_];
00113 bzero((void *)grid_[i], sizeof(MobileNode *)*dim_y_);
00114 }
00115 return (TCL_OK);
00116 }
00117 return (TclObject::command(argc, argv));
00118 }
00119
00120 void GridKeeper::new_moves(MobileNode *mn)
00121 {
00122 double x = mn->X(), y = mn->Y();
00123 double ss = mn->speed();
00124 double vx = (mn->dX())*ss, vy = (mn->dY())*ss;
00125
00126 double endx, endy, pother, tm;
00127 int i, j, endi, gother, grid_x, grid_y;
00128 MoveEvent *me;
00129
00130 Scheduler& s = Scheduler::instance();
00131
00132 endx = mn->destX();
00133 endy = mn->destY();
00134
00135 if (vx > 0) {
00136 endi = min(dim_x_-1, (int)endx);
00137 for (i = (int)x+1; i <= endi; i++) {
00138 tm = (i-x)/vx;
00139 pother = vy*tm + y;
00140 j = (int)pother;
00141 me = new MoveEvent;
00142 if (j == pother && j != 0 && j != dim_y_) {
00143 if (vy > 0) gother = j - 1;
00144 else if (vy < 0) gother = j + 1;
00145 else gother = j;
00146 }
00147 else {
00148 gother = j;
00149 }
00150 me->leave_ = &(grid_[aligngrid(i-1, dim_x_)][aligngrid(gother, dim_y_)]);
00151
00152 me->grid_x_ = grid_x = aligngrid(i, dim_x_);
00153 me->grid_y_ = grid_y = aligngrid(j, dim_y_);
00154 me->enter_ = &(grid_[grid_x][grid_y]);
00155 me->token_ = mn;
00156 s.schedule(gh_, me, tm);
00157 }
00158 }
00159 else if (vx < 0) {
00160 endi = (int)endx;
00161 for (i = (int)x; i > endi; i--) {
00162 if (i == dim_x_) continue;
00163 tm = (i-x)/vx;
00164 pother = vy*tm + y;
00165 j = (int)pother;
00166 me = new MoveEvent;
00167 if (j == pother && j != 0 && j != dim_y_) {
00168 if (vy > 0) gother = j - 1;
00169 else if (vy < 0) gother = j + 1;
00170 else gother = j;
00171 }
00172 else {
00173 gother = j;
00174 }
00175 me->leave_ = &grid_[aligngrid(i, dim_x_)][aligngrid(gother, dim_y_)];
00176
00177 me->grid_x_ = grid_x = aligngrid(i-1, dim_x_);
00178 me->grid_y_ = grid_y = aligngrid(j, dim_y_);
00179 me->enter_ = &grid_[grid_x][grid_y];
00180 me->token_ = mn;
00181 s.schedule(gh_, me, tm);
00182 }
00183 }
00184 if (vy > 0) {
00185 endi = min(dim_y_-1, (int)endy);
00186 for (j = (int)y+1; j <= endi; j++) {
00187 tm = (j-y)/vy;
00188 pother = vx*tm + x;
00189 i = (int)pother;
00190 me = new MoveEvent;
00191 if (i == pother && i != 0 && i != dim_x_ && vx != 0) continue;
00192 me->leave_ = &grid_[aligngrid(i, dim_x_)][aligngrid(j-1, dim_y_)];
00193
00194 me->grid_x_ = grid_x = aligngrid(i, dim_x_);
00195 me->grid_y_ = grid_y = aligngrid(j, dim_y_);
00196 me->enter_ = &grid_[grid_x][grid_y];
00197 me->token_ = mn;
00198
00199 s.schedule(gh_, me, tm);
00200 }
00201 }
00202 else if (vy < 0) {
00203 endi = (int)endy;
00204 for (j = (int)y; j > endi; j--) {
00205 if (j == dim_y_) continue;
00206 tm = (j-y)/vy;
00207 pother = vx*tm + x;
00208 i = (int)pother;
00209 me = new MoveEvent;
00210 if (i == pother && i != 0 && i != dim_x_ && vx != 0) continue;
00211 me->leave_ = &grid_[aligngrid(i, dim_x_)][aligngrid(j, dim_y_)];
00212
00213 me->grid_x_ = grid_x = aligngrid(i, dim_x_);
00214 me->grid_y_ = grid_y = aligngrid(j-1, dim_y_);
00215 me->enter_ = &grid_[grid_x][grid_y];
00216 me->token_ = mn;
00217 s.schedule(gh_, me, tm);
00218 }
00219 }
00220
00221 }
00222
00223 int GridKeeper::get_neighbors(MobileNode* mn, MobileNode **output)
00224 {
00225 int grid_x, grid_y, index = 0, i, j, ulx, uly, lly, adj;
00226 MobileNode *pgd;
00227 double mnx, mny, mnr, sqmnr;
00228
00229 mn->update_position();
00230 mnx = mn->X();
00231 mny = mn->Y();
00232
00233 grid_x = aligngrid((int)mn->X(), dim_x_);
00234 grid_y = aligngrid((int)mn->Y(), dim_y_);
00235
00236 sqmnr = (mnr = mn->radius())*mnr;
00237
00238 adj = (int)ceil(mnr);
00239
00240 ulx = min(dim_x_-1, grid_x + adj);
00241 uly = min(dim_y_-1, grid_y + adj);
00242 lly = max(0, grid_y - adj);
00243
00244 for (i = max(0, grid_x - adj); i <= ulx; i++) {
00245 for (j = lly; j <= uly; j++) {
00246 for (pgd = grid_[i][j]; pgd != 0; pgd = pgd->next()) {
00247 if (mn->address() == pgd->address())
00248 continue;
00249 pgd->update_position();
00250 if (d2(pgd->X(), mnx, pgd->Y(), mny) < sqmnr)
00251 output[index++] = pgd;
00252 }
00253 }
00254 }
00255
00256 return index;
00257 }
00258
00259 void GridKeeper::dump()
00260 {
00261 int i,j;
00262 MobileNode *pgd;
00263
00264 for (i = 0; i< dim_x_; i++) {
00265 for (j = 0; j < dim_y_; j++) {
00266 if (grid_[i][j] == 0) continue;
00267 printf("grid[%d][%d]: ",i,j);
00268 for (pgd = grid_[i][j]; pgd != 0; pgd = pgd->next()) {
00269 printf("%d ",pgd->address());
00270 }
00271 printf("\n");
00272 }
00273 }
00274 printf("-------------------------------\n");
00275
00276 }
00277
00278