00001
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
00034
00035
00036
00037
00038 #include <dynamicEDT3D/dynamicEDT3D.h>
00039
00040 #include <math.h>
00041 #include <stdlib.h>
00042
00043 #define FOR_EACH_NEIGHBOR_WITH_CHECK(function, p, ...) \
00044 int x=p.x;\
00045 int y=p.y;\
00046 int z=p.z;\
00047 int xp1 = x+1;\
00048 int xm1 = x-1;\
00049 int yp1 = y+1;\
00050 int ym1 = y-1;\
00051 int zp1 = z+1;\
00052 int zm1 = z-1;\
00053 \
00054 if(z<sizeZm1) function(x, y, zp1, ##__VA_ARGS__);\
00055 if(z>0) function(x, y, zm1, ##__VA_ARGS__);\
00056 \
00057 if(y<sizeYm1){\
00058 function(x, yp1, z, ##__VA_ARGS__);\
00059 if(z<sizeZm1) function(x, yp1, zp1, ##__VA_ARGS__);\
00060 if(z>0) function(x, yp1, zm1, ##__VA_ARGS__);\
00061 }\
00062 \
00063 if(y>0){\
00064 function(x, ym1, z, ##__VA_ARGS__);\
00065 if(z<sizeZm1) function(x, ym1, zp1, ##__VA_ARGS__);\
00066 if(z>0) function(x, ym1, zm1, ##__VA_ARGS__);\
00067 }\
00068 \
00069 \
00070 if(x<sizeXm1){\
00071 function(xp1, y, z, ##__VA_ARGS__);\
00072 if(z<sizeZm1) function(xp1, y, zp1, ##__VA_ARGS__);\
00073 if(z>0) function(xp1, y, zm1, ##__VA_ARGS__);\
00074 \
00075 if(y<sizeYm1){\
00076 function(xp1, yp1, z, ##__VA_ARGS__);\
00077 if(z<sizeZm1) function(xp1, yp1, zp1, ##__VA_ARGS__);\
00078 if(z>0) function(xp1, yp1, zm1, ##__VA_ARGS__);\
00079 }\
00080 \
00081 if(y>0){\
00082 function(xp1, ym1, z, ##__VA_ARGS__);\
00083 if(z<sizeZm1) function(xp1, ym1, zp1, ##__VA_ARGS__);\
00084 if(z>0) function(xp1, ym1, zm1, ##__VA_ARGS__);\
00085 }\
00086 }\
00087 \
00088 if(x>0){\
00089 function(xm1, y, z, ##__VA_ARGS__);\
00090 if(z<sizeZm1) function(xm1, y, zp1, ##__VA_ARGS__);\
00091 if(z>0) function(xm1, y, zm1, ##__VA_ARGS__);\
00092 \
00093 if(y<sizeYm1){\
00094 function(xm1, yp1, z, ##__VA_ARGS__);\
00095 if(z<sizeZm1) function(xm1, yp1, zp1, ##__VA_ARGS__);\
00096 if(z>0) function(xm1, yp1, zm1, ##__VA_ARGS__);\
00097 }\
00098 \
00099 if(y>0){\
00100 function(xm1, ym1, z, ##__VA_ARGS__);\
00101 if(z<sizeZm1) function(xm1, ym1, zp1, ##__VA_ARGS__);\
00102 if(z>0) function(xm1, ym1, zm1, ##__VA_ARGS__);\
00103 }\
00104 }
00105
00106 float DynamicEDT3D::distanceValue_Error = -1.0;
00107 int DynamicEDT3D::distanceInCellsValue_Error = -1;
00108
00109 DynamicEDT3D::DynamicEDT3D(int _maxdist_squared) {
00110 sqrt2 = sqrt(2.0);
00111 maxDist_squared = _maxdist_squared;
00112 maxDist = sqrt((double) maxDist_squared);
00113 data = NULL;
00114 gridMap = NULL;
00115 }
00116
00117 DynamicEDT3D::~DynamicEDT3D() {
00118 if (data) {
00119 for (int x=0; x<sizeX; x++){
00120 for (int y=0; y<sizeY; y++)
00121 delete[] data[x][y];
00122
00123 delete[] data[x];
00124 }
00125 delete[] data;
00126 }
00127
00128 if (gridMap) {
00129 for (int x=0; x<sizeX; x++){
00130 for (int y=0; y<sizeY; y++)
00131 delete[] gridMap[x][y];
00132
00133 delete[] gridMap[x];
00134 }
00135 delete[] gridMap;
00136 }
00137 }
00138
00139 void DynamicEDT3D::initializeEmpty(int _sizeX, int _sizeY, int _sizeZ, bool initGridMap) {
00140 sizeX = _sizeX;
00141 sizeY = _sizeY;
00142 sizeZ = _sizeZ;
00143
00144 sizeXm1 = sizeX-1;
00145 sizeYm1 = sizeY-1;
00146 sizeZm1 = sizeZ-1;
00147
00148 if (data) {
00149 for (int x=0; x<sizeX; x++){
00150 for (int y=0; y<sizeY; y++)
00151 delete[] data[x][y];
00152
00153 delete[] data[x];
00154 }
00155 delete[] data;
00156 }
00157
00158 data = new dataCell**[sizeX];
00159 for (int x=0; x<sizeX; x++){
00160 data[x] = new dataCell*[sizeY];
00161 for(int y=0; y<sizeY; y++)
00162 data[x][y] = new dataCell[sizeZ];
00163 }
00164
00165 if (initGridMap) {
00166 if (gridMap) {
00167 for (int x=0; x<sizeX; x++){
00168 for (int y=0; y<sizeY; y++)
00169 delete[] gridMap[x][y];
00170
00171 delete[] gridMap[x];
00172 }
00173 delete[] gridMap;
00174 }
00175
00176 gridMap = new bool**[sizeX];
00177 for (int x=0; x<sizeX; x++){
00178 gridMap[x] = new bool*[sizeY];
00179 for (int y=0; y<sizeY; y++)
00180 gridMap[x][y] = new bool[sizeZ];
00181 }
00182 }
00183
00184 dataCell c;
00185 c.dist = maxDist;
00186 c.sqdist = maxDist_squared;
00187 c.obstX = invalidObstData;
00188 c.obstY = invalidObstData;
00189 c.obstZ = invalidObstData;
00190 c.queueing = fwNotQueued;
00191 c.needsRaise = false;
00192
00193 for (int x=0; x<sizeX; x++){
00194 for (int y=0; y<sizeY; y++){
00195 for (int z=0; z<sizeZ; z++){
00196 data[x][y][z] = c;
00197 }
00198 }
00199 }
00200
00201 if (initGridMap) {
00202 for (int x=0; x<sizeX; x++)
00203 for (int y=0; y<sizeY; y++)
00204 for (int z=0; z<sizeZ; z++)
00205 gridMap[x][y][z] = 0;
00206 }
00207 }
00208
00209 void DynamicEDT3D::initializeMap(int _sizeX, int _sizeY, int _sizeZ, bool*** _gridMap) {
00210 gridMap = _gridMap;
00211 initializeEmpty(_sizeX, _sizeY, _sizeZ, false);
00212
00213 for (int x=0; x<sizeX; x++) {
00214 for (int y=0; y<sizeY; y++) {
00215 for (int z=0; z<sizeZ; z++) {
00216 if (gridMap[x][y][z]) {
00217 dataCell c = data[x][y][z];
00218 if (!isOccupied(x,y,z,c)) {
00219
00220 bool isSurrounded = true;
00221 for (int dx=-1; dx<=1; dx++) {
00222 int nx = x+dx;
00223 if (nx<0 || nx>sizeX-1) continue;
00224 for (int dy=-1; dy<=1; dy++) {
00225 int ny = y+dy;
00226 if (ny<0 || ny>sizeY-1) continue;
00227 for (int dz=-1; dz<=1; dz++) {
00228 if (dx==0 && dy==0 && dz==0) continue;
00229 int nz = z+dz;
00230 if (nz<0 || nz>sizeZ-1) continue;
00231
00232 if (!gridMap[nx][ny][nz]) {
00233 isSurrounded = false;
00234 break;
00235 }
00236 }
00237 }
00238 }
00239 if (isSurrounded) {
00240 c.obstX = x;
00241 c.obstY = y;
00242 c.obstZ = z;
00243 c.sqdist = 0;
00244 c.dist = 0;
00245 c.queueing = fwProcessed;
00246 data[x][y][z] = c;
00247 } else setObstacle(x,y,z);
00248 }
00249 }
00250 }
00251 }
00252 }
00253 }
00254
00255 void DynamicEDT3D::occupyCell(int x, int y, int z) {
00256 gridMap[x][y][z] = 1;
00257 setObstacle(x,y,z);
00258 }
00259
00260 void DynamicEDT3D::clearCell(int x, int y, int z) {
00261 gridMap[x][y][z] = 0;
00262 removeObstacle(x,y,z);
00263 }
00264
00265 void DynamicEDT3D::setObstacle(int x, int y, int z) {
00266 dataCell c = data[x][y][z];
00267 if(isOccupied(x,y,z,c)) return;
00268
00269 addList.push_back(INTPOINT3D(x,y,z));
00270 c.obstX = x;
00271 c.obstY = y;
00272 c.obstZ = z;
00273 data[x][y][z] = c;
00274 }
00275
00276 void DynamicEDT3D::removeObstacle(int x, int y, int z) {
00277 dataCell c = data[x][y][z];
00278 if(isOccupied(x,y,z,c) == false) return;
00279
00280 removeList.push_back(INTPOINT3D(x,y,z));
00281 c.obstX = invalidObstData;
00282 c.obstY = invalidObstData;
00283 c.obstZ = invalidObstData;
00284 c.queueing = bwQueued;
00285 data[x][y][z] = c;
00286 }
00287
00288 void DynamicEDT3D::exchangeObstacles(std::vector<INTPOINT3D> points) {
00289
00290 for (unsigned int i=0; i<lastObstacles.size(); i++) {
00291 int x = lastObstacles[i].x;
00292 int y = lastObstacles[i].y;
00293 int z = lastObstacles[i].z;
00294
00295 bool v = gridMap[x][y][z];
00296 if (v) continue;
00297 removeObstacle(x,y,z);
00298 }
00299
00300 lastObstacles.clear();
00301
00302 for (unsigned int i=0; i<points.size(); i++) {
00303 int x = points[i].x;
00304 int y = points[i].y;
00305 int z = points[i].z;
00306 bool v = gridMap[x][y][z];
00307 if (v) continue;
00308 setObstacle(x,y,z);
00309 lastObstacles.push_back(points[i]);
00310 }
00311 }
00312
00313 void DynamicEDT3D::update(bool updateRealDist) {
00314 commitAndColorize(updateRealDist);
00315
00316 while (!open.empty()) {
00317 INTPOINT3D p = open.pop();
00318 int x = p.x;
00319 int y = p.y;
00320 int z = p.z;
00321 dataCell c = data[x][y][z];
00322
00323 if(c.queueing==fwProcessed) continue;
00324
00325 if (c.needsRaise) {
00326
00327 raiseCell(p, c, updateRealDist);
00328 data[x][y][z] = c;
00329 }
00330 else if (c.obstX != invalidObstData && isOccupied(c.obstX,c.obstY,c.obstZ,data[c.obstX][c.obstY][c.obstZ])) {
00331
00332 propagateCell(p, c, updateRealDist);
00333 data[x][y][z] = c;
00334 }
00335 }
00336 }
00337
00338 void DynamicEDT3D::raiseCell(INTPOINT3D &p, dataCell &c, bool updateRealDist){
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356 FOR_EACH_NEIGHBOR_WITH_CHECK(inspectCellRaise,p, updateRealDist)
00357
00358 c.needsRaise = false;
00359 c.queueing = bwProcessed;
00360 }
00361
00362 void DynamicEDT3D::inspectCellRaise(int &nx, int &ny, int &nz, bool updateRealDist){
00363 dataCell nc = data[nx][ny][nz];
00364 if (nc.obstX!=invalidObstData && !nc.needsRaise) {
00365 if(!isOccupied(nc.obstX,nc.obstY,nc.obstZ,data[nc.obstX][nc.obstY][nc.obstZ])) {
00366 open.push(nc.sqdist, INTPOINT3D(nx,ny,nz));
00367 nc.queueing = fwQueued;
00368 nc.needsRaise = true;
00369 nc.obstX = invalidObstData;
00370 nc.obstY = invalidObstData;
00371 nc.obstZ = invalidObstData;
00372 if (updateRealDist) nc.dist = maxDist;
00373 nc.sqdist = maxDist_squared;
00374 data[nx][ny][nz] = nc;
00375 } else {
00376 if(nc.queueing != fwQueued){
00377 open.push(nc.sqdist, INTPOINT3D(nx,ny,nz));
00378 nc.queueing = fwQueued;
00379 data[nx][ny][nz] = nc;
00380 }
00381 }
00382 }
00383 }
00384
00385 void DynamicEDT3D::propagateCell(INTPOINT3D &p, dataCell &c, bool updateRealDist){
00386 c.queueing = fwProcessed;
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405 if(c.sqdist==0){
00406 FOR_EACH_NEIGHBOR_WITH_CHECK(inspectCellPropagate, p, c, updateRealDist)
00407 } else {
00408 int x=p.x;
00409 int y=p.y;
00410 int z=p.z;
00411 int xp1 = x+1;
00412 int xm1 = x-1;
00413 int yp1 = y+1;
00414 int ym1 = y-1;
00415 int zp1 = z+1;
00416 int zm1 = z-1;
00417
00418 int dpx = (x - c.obstX);
00419 int dpy = (y - c.obstY);
00420 int dpz = (z - c.obstZ);
00421
00422
00423
00424
00425
00426 if(dpz >=0 && z<sizeZm1) inspectCellPropagate(x, y, zp1, c, updateRealDist);
00427 if(dpz <=0 && z>0) inspectCellPropagate(x, y, zm1, c, updateRealDist);
00428
00429 if(dpy>=0 && y<sizeYm1){
00430 inspectCellPropagate(x, yp1, z, c, updateRealDist);
00431 if(dpz >=0 && z<sizeZm1) inspectCellPropagate(x, yp1, zp1, c, updateRealDist);
00432 if(dpz <=0 && z>0) inspectCellPropagate(x, yp1, zm1, c, updateRealDist);
00433 }
00434
00435 if(dpy<=0 && y>0){
00436 inspectCellPropagate(x, ym1, z, c, updateRealDist);
00437 if(dpz >=0 && z<sizeZm1) inspectCellPropagate(x, ym1, zp1, c, updateRealDist);
00438 if(dpz <=0 && z>0) inspectCellPropagate(x, ym1, zm1, c, updateRealDist);
00439 }
00440
00441
00442 if(dpx>=0 && x<sizeXm1){
00443 inspectCellPropagate(xp1, y, z, c, updateRealDist);
00444 if(dpz >=0 && z<sizeZm1) inspectCellPropagate(xp1, y, zp1, c, updateRealDist);
00445 if(dpz <=0 && z>0) inspectCellPropagate(xp1, y, zm1, c, updateRealDist);
00446
00447 if(dpy>=0 && y<sizeYm1){
00448 inspectCellPropagate(xp1, yp1, z, c, updateRealDist);
00449 if(dpz >=0 && z<sizeZm1) inspectCellPropagate(xp1, yp1, zp1, c, updateRealDist);
00450 if(dpz <=0 && z>0) inspectCellPropagate(xp1, yp1, zm1, c, updateRealDist);
00451 }
00452
00453 if(dpy<=0 && y>0){
00454 inspectCellPropagate(xp1, ym1, z, c, updateRealDist);
00455 if(dpz >=0 && z<sizeZm1) inspectCellPropagate(xp1, ym1, zp1, c, updateRealDist);
00456 if(dpz <=0 && z>0) inspectCellPropagate(xp1, ym1, zm1, c, updateRealDist);
00457 }
00458 }
00459
00460 if(dpx<=0 && x>0){
00461 inspectCellPropagate(xm1, y, z, c, updateRealDist);
00462 if(dpz >=0 && z<sizeZm1) inspectCellPropagate(xm1, y, zp1, c, updateRealDist);
00463 if(dpz <=0 && z>0) inspectCellPropagate(xm1, y, zm1, c, updateRealDist);
00464
00465 if(dpy>=0 && y<sizeYm1){
00466 inspectCellPropagate(xm1, yp1, z, c, updateRealDist);
00467 if(dpz >=0 && z<sizeZm1) inspectCellPropagate(xm1, yp1, zp1, c, updateRealDist);
00468 if(dpz <=0 && z>0) inspectCellPropagate(xm1, yp1, zm1, c, updateRealDist);
00469 }
00470
00471 if(dpy<=0 && y>0){
00472 inspectCellPropagate(xm1, ym1, z, c, updateRealDist);
00473 if(dpz >=0 && z<sizeZm1) inspectCellPropagate(xm1, ym1, zp1, c, updateRealDist);
00474 if(dpz <=0 && z>0) inspectCellPropagate(xm1, ym1, zm1, c, updateRealDist);
00475 }
00476 }
00477 }
00478 }
00479
00480 void DynamicEDT3D::inspectCellPropagate(int &nx, int &ny, int &nz, dataCell &c, bool updateRealDist){
00481 dataCell nc = data[nx][ny][nz];
00482 if(!nc.needsRaise) {
00483 int distx = nx-c.obstX;
00484 int disty = ny-c.obstY;
00485 int distz = nz-c.obstZ;
00486 int newSqDistance = distx*distx + disty*disty + distz*distz;
00487 if(newSqDistance > maxDist_squared)
00488 newSqDistance = maxDist_squared;
00489 bool overwrite = (newSqDistance < nc.sqdist);
00490 if(!overwrite && newSqDistance==nc.sqdist) {
00491
00492 if (nc.obstX == invalidObstData){
00493 overwrite = true;
00494 }
00495 else {
00496
00497 dataCell tmp = data[nc.obstX][nc.obstY][nc.obstZ];
00498
00499 if((tmp.obstX==nc.obstX && tmp.obstY==nc.obstY && tmp.obstZ==nc.obstZ)==false)
00500 overwrite = true;
00501 }
00502 }
00503 if (overwrite) {
00504 if(newSqDistance < maxDist_squared){
00505 open.push(newSqDistance, INTPOINT3D(nx,ny,nz));
00506 nc.queueing = fwQueued;
00507 }
00508 if (updateRealDist) {
00509 nc.dist = sqrt((double) newSqDistance);
00510 }
00511 nc.sqdist = newSqDistance;
00512 nc.obstX = c.obstX;
00513 nc.obstY = c.obstY;
00514 nc.obstZ = c.obstZ;
00515 }
00516 data[nx][ny][nz] = nc;
00517 }
00518 }
00519
00520
00521 float DynamicEDT3D::getDistance( int x, int y, int z ) const {
00522 if( (x>=0) && (x<sizeX) && (y>=0) && (y<sizeY) && (z>=0) && (z<sizeZ)){
00523 return data[x][y][z].dist;
00524 }
00525 else return distanceValue_Error;
00526 }
00527
00528 INTPOINT3D DynamicEDT3D::getClosestObstacle( int x, int y, int z ) const {
00529 if( (x>=0) && (x<sizeX) && (y>=0) && (y<sizeY) && (z>=0) && (z<sizeZ)){
00530 dataCell c = data[x][y][z];
00531 return INTPOINT3D(c.obstX, c.obstY, c.obstZ);
00532 }
00533 else return INTPOINT3D(invalidObstData, invalidObstData, invalidObstData);
00534 }
00535
00536 int DynamicEDT3D::getSQCellDistance( int x, int y, int z ) const {
00537 if( (x>=0) && (x<sizeX) && (y>=0) && (y<sizeY) && (z>=0) && (z<sizeZ)){
00538 return data[x][y][z].sqdist;
00539 }
00540 else return distanceInCellsValue_Error;
00541 }
00542
00543
00544 void DynamicEDT3D::commitAndColorize(bool updateRealDist) {
00545
00546 for (unsigned int i=0; i<addList.size(); i++) {
00547 INTPOINT3D p = addList[i];
00548 int x = p.x;
00549 int y = p.y;
00550 int z = p.z;
00551 dataCell c = data[x][y][z];
00552
00553 if(c.queueing != fwQueued){
00554 if (updateRealDist) c.dist = 0;
00555 c.sqdist = 0;
00556 c.obstX = x;
00557 c.obstY = y;
00558 c.obstZ = z;
00559 c.queueing = fwQueued;
00560 data[x][y][z] = c;
00561 open.push(0, INTPOINT3D(x,y,z));
00562 }
00563 }
00564
00565
00566 for (unsigned int i=0; i<removeList.size(); i++) {
00567 INTPOINT3D p = removeList[i];
00568 int x = p.x;
00569 int y = p.y;
00570 int z = p.z;
00571 dataCell c = data[x][y][z];
00572
00573 if (isOccupied(x,y,z,c)==true) continue;
00574 open.push(0, INTPOINT3D(x,y,z));
00575 if (updateRealDist) c.dist = maxDist;
00576 c.sqdist = maxDist_squared;
00577 c.needsRaise = true;
00578 data[x][y][z] = c;
00579 }
00580 removeList.clear();
00581 addList.clear();
00582 }
00583
00584 bool DynamicEDT3D::isOccupied(int x, int y, int z) const {
00585 dataCell c = data[x][y][z];
00586 return (c.obstX==x && c.obstY==y && c.obstZ==z);
00587 }
00588
00589 bool DynamicEDT3D::isOccupied(int &x, int &y, int &z, dataCell &c) {
00590 return (c.obstX==x && c.obstY==y && c.obstZ==z);
00591 }