00001 #include "space.h"
00002
00003 #include <math.h>
00004 #include <fstream>
00005 #include <iostream>
00006
00007 #include "box.h"
00008 #include "container.h"
00009 #include "face.h"
00010 #include "object.h"
00011 #include "vertex.h"
00012
00013 using std::cout;
00014 using std::endl;
00015 using std::left;
00016
00017 Space * Space::only_one = NULL;
00018
00019 Space & Space::instance(void)
00020 {
00021
00022
00023 if (only_one == NULL)
00024 only_one = new Space();
00025
00026 return *only_one;
00027 }
00028
00029 Space::Space (void)
00030 :axes(3,0),world(6,0),b()
00031 {
00032 cout << "Initializing space data structure..............";
00033 cout.flush();
00034 boundWorld();
00035 initBoxes();
00036 initFile();
00037 cout << "complete.\n";
00038 cout.flush();
00039 }
00040
00041 Space::Space (const Space & rhs)
00042 :axes(3,0),world(6,0),b()
00043 {
00044 cout << "Copy constructor prohibited on instances of Space class.\n";
00045 cout << "Space " << rhs.world.size() << endl;
00046 exit(0);
00047 }
00048
00049 Space& Space::operator= (const Space& rhs)
00050 {
00051 cout << "Copy assignment operator prohibited on instances of Space class.\n";
00052 cout << "Space " << rhs.world.size() << endl;
00053 exit(0);
00054 }
00055
00056 int Space::screenIndex (int i,char const * const c) const
00057 {
00058 int a=0;
00059 if (!strcmp(c,"x")){a=axes[0]-1;}
00060 else if (!strcmp(c,"y")){a=axes[1]-1;}
00061 else if (!strcmp(c,"z")){a=axes[2]-1;}
00062 else {cout << "Received unexpected string.\n";exit(0);}
00063
00064 if (i<0){i=0;}
00065 if (i>a){i=a;}
00066 return i;
00067 }
00068
00069 void Space::getBoxesFromPosition (vec_d const & origin,vec_d const & eend,vec_bp& bp) const
00070 {
00071
00072 int br[6];
00073
00074 br[0] = location2Index(origin[0],"x");
00075 br[1] = location2Index( eend[0],"x");
00076 br[2] = location2Index(origin[1],"y");
00077 br[3] = location2Index( eend[1],"y");
00078 br[4] = location2Index(origin[2],"z");
00079 br[5] = location2Index( eend[2],"z");
00080
00081 bp.reserve(VECTOR_RESERVE);
00082 getBoxesFromIndices(NULL,br,bp);
00083 }
00084
00085 void Space::getBoxesFromIndices (int const * const oldbr,int const * const newbr,vec_bp& bp) const
00086 {
00087
00088
00089
00090
00091
00092 int x0=0,x1=0,y0=0,y1=0,z0=0,z1=0;
00093 if(newbr[0]<newbr[1]) { x0 = newbr[0]; x1 = newbr[1]; }
00094 else { x0 = newbr[1]; x1 = newbr[0]; }
00095 if(newbr[2]<newbr[3]) { y0 = newbr[2]; y1 = newbr[3]; }
00096 else { y0 = newbr[3]; y1 = newbr[2]; }
00097 if(newbr[4]<newbr[5]) { z0 = newbr[4]; z1 = newbr[5]; }
00098 else { z0 = newbr[5]; z1 = newbr[4]; }
00099
00100
00101 int X0=0,X1=0,Y0=0,Y1=0,Z0=0,Z1=0;
00102 if (oldbr!=NULL)
00103 {
00104 if(oldbr[0]<oldbr[1]) { X0 = oldbr[0]; X1 = oldbr[1]; }
00105 else { X0 = oldbr[1]; X1 = oldbr[0]; }
00106 if(oldbr[2]<oldbr[3]) { Y0 = oldbr[2]; Y1 = oldbr[3]; }
00107 else { Y0 = oldbr[3]; Y1 = oldbr[2]; }
00108 if(oldbr[4]<oldbr[5]) { Z0 = oldbr[4]; Z1 = oldbr[5]; }
00109 else { Z0 = oldbr[5]; Z1 = oldbr[4]; }
00110 }
00111
00112 b_cit i = b.begin()+axes[0]*((z0-1)*axes[1]+(y0-1));
00113 for (int z = z0;z<z1+1;z++)
00114 {
00115 i += axes[0]*axes[1];
00116 for (int y = y0;y<y1+1;y++)
00117 {
00118 i += axes[0];
00119 for (int x = x0;x<x1+1;x++)
00120 {
00121 if(oldbr != NULL)
00122 {
00123 if ((x<X0||x>X1) ||
00124 (y<Y0||y>Y1) ||
00125 (z<Z0||z>Z1))
00126 {
00127 bp.push_back(const_cast<Box*>(&(*(i+x))));
00128 }
00129 }
00130 else
00131 {
00132 bp.push_back(const_cast<Box*>(&(*(i+x))));
00133 }
00134 }
00135 }
00136 i-=(y1-y0+1)*axes[0];
00137 }
00138 if(bp.empty()==true)
00139 {
00140 cout << "\n\nSpace::getBoxesFromIndices\n"
00141 << "newbr ["
00142 << newbr[0] << ","
00143 << newbr[1] << ","
00144 << newbr[2] << ","
00145 << newbr[3] << ","
00146 << newbr[4] << ","
00147 << newbr[5] << "]\n";
00148 if (oldbr != NULL)
00149 {
00150 cout
00151 << "oldbr ["
00152 << oldbr[0] << ","
00153 << oldbr[1] << ","
00154 << oldbr[2] << ","
00155 << oldbr[3] << ","
00156 << oldbr[4] << ","
00157 << oldbr[5] << "]\n"
00158 << endl << endl;
00159 }
00160 else
00161 { cout
00162 << "oldbr == NULL["
00163 << endl << endl;
00164 }
00165 exit(0);
00166 }
00167 }
00168
00169 int Space::indices2Index (int const x,int const y,int const z) const
00170 {
00171 return axes[0]*(z*axes[1]+y)+x;
00172 }
00173
00174 int Space::location2Index (double const ss,char const * const c) const
00175 {
00176
00177
00178
00179
00180
00181 int a=0;
00182 if (!strcmp(c,"x"))
00183 {
00184 a = static_cast<int>(floor( (ss-world[0])/(SPACE_LENGTH*SCALE) ));
00185 a = screenIndex(a,"x");
00186 }
00187 else if (!strcmp(c,"y"))
00188 {
00189 a = static_cast<int>(floor( (ss-world[2])/(SPACE_LENGTH*SCALE) ));
00190 a = screenIndex(a,"y");
00191 }
00192 else if (!strcmp(c,"z"))
00193 {
00194 a = static_cast<int>(floor( (ss-world[4])/(SPACE_LENGTH*SCALE) ));
00195 a = screenIndex(a,"z");
00196 }
00197 else
00198 {
00199 cout << "\n\nSpace::location2Index: Error. Received unexpected string.\n";
00200 cout << "Space::location2Index: string = " << c << endl;
00201 exit(0);
00202 }
00203 return a;
00204 }
00205
00206 void Space::initBoxes (void)
00207 {
00208
00209 double a = 1.0/(SPACE_LENGTH*SCALE);
00210 axes[0] = (int) ceil( a*(world[1]-world[0]) );
00211 axes[1] = (int) ceil( a*(world[3]-world[2]) );
00212 axes[2] = (int) ceil( a*(world[5]-world[4]) );
00213
00214 b.reserve(axes[0]*axes[1]*axes[2]);
00215
00216
00217 for (int z =0;z<axes[2];z++)
00218 {
00219 for (int y =0;y<axes[1];y++)
00220 {
00221 for (int x =0;x<axes[0];x++)
00222 {
00223 b.push_back(Box(x,y,z));
00224 }
00225 }
00226 }
00227 }
00228
00229 void Space::boundWorld (void)
00230 {
00231 double xmin,xmax,ymin,ymax,zmin,zmax,range[6];
00232
00233 xmin = Container::instance().o[0].v[0].getCoord(0);
00234 xmax = Container::instance().o[0].v[0].getCoord(0);
00235 ymin = Container::instance().o[0].v[0].getCoord(1);
00236 ymax = Container::instance().o[0].v[0].getCoord(1);
00237 zmin = Container::instance().o[0].v[0].getCoord(2);
00238 zmax = Container::instance().o[0].v[0].getCoord(2);
00240
00241 for (o_cit i=Container::instance().o.begin();i!=Container::instance().o.end();i++)
00242 {
00243
00244 i->boundObject(&range[0]);
00245 if (range[1]>xmax) {xmax = range[1];}
00246 if (range[0]<xmin) {xmin = range[0];}
00247 if (range[3]>ymax) {ymax = range[3];}
00248 if (range[2]<ymin) {ymin = range[2];}
00249 if (range[5]>zmax) {zmax = range[5];}
00250 if (range[4]<zmin) {zmin = range[4];}
00251 }
00252 if (xmin<0) {world[0]=xmin*1.01;} else {world[0]=xmin*0.99;}
00253 if (xmax<0) {world[1]=xmax*0.99;} else {world[1]=xmax*1.01;}
00254 if (ymin<0) {world[2]=ymin*1.01;} else {world[2]=ymin*0.99;}
00255 if (ymax<0) {world[3]=ymax*0.99;} else {world[3]=ymax*1.01;}
00256 if (zmin<0) {world[4]=zmin*1.01;} else {world[4]=zmin*0.99;}
00257 if (zmax<0) {world[5]=zmax*0.99;} else {world[5]=zmax*1.01;}
00258
00259 if (PRINT_FLAG)
00260 {
00261 cout << "\nworld bounds = ["
00262 << world[0] << " "
00263 << world[1] << " "
00264 << world[2] << " "
00265 << world[3] << " "
00266 << world[4] << " "
00267 << world[5] << "]\n";
00268 }
00269 }
00270
00271 void Space::getBoxesToCheck (Face const * const f,vec_bp &bp) const
00272 {
00273
00274 std::vector<double> xv(3,0),yv(3,0),zv(3,0),min(3,0),max(3,0);
00275 xv[0]=f->getVertex(0)->getCoord(0);
00276 xv[1]=f->getVertex(1)->getCoord(0);
00277 xv[2]=f->getVertex(2)->getCoord(0);
00278 yv[0]=f->getVertex(0)->getCoord(1);
00279 yv[1]=f->getVertex(1)->getCoord(1);
00280 yv[2]=f->getVertex(2)->getCoord(1);
00281 zv[0]=f->getVertex(0)->getCoord(2);
00282 zv[1]=f->getVertex(1)->getCoord(2);
00283 zv[2]=f->getVertex(2)->getCoord(2);
00284 sort(xv.begin(),xv.end());
00285 sort(yv.begin(),yv.end());
00286 sort(zv.begin(),zv.end());
00287
00288 min[0] = xv[0];
00289 min[1] = yv[0];
00290 min[2] = zv[0];
00291 max[0] = xv[2];
00292 max[1] = yv[2];
00293 max[2] = zv[2];
00294
00295 getBoxesFromPosition(min,max,bp);
00296 }
00297
00298 void Space::initFile (void)
00299 {
00300 std::ofstream Sfile;
00301 str file = OUTPUT_DATA_DIR + SPACE_LOG_FILE;
00302 Sfile.open(file.c_str());
00303 Sfile.width(15);
00304 Sfile << left << "#boxes(x,y,z)";
00305 Sfile.width(15);
00306 Sfile << left << "total #boxes";
00307 Sfile.width(30);
00308 Sfile << left << "world bounds [xmin xmax ymin ymax zmin zmax]" << endl;
00309 char str[15];
00310 sprintf(str,"%d,%d,%d",axes[0],axes[1],axes[2]);
00311 Sfile.width(15);
00312 Sfile << left << str;
00313 Sfile.width(15);
00314 Sfile << left << axes[0]*axes[1]*axes[2];
00315 Sfile << "[" << world[0] << " " << world[1] << " " << world[2] << " "
00316 << world[3] << " " << world[4] << " " << world[5] << "]\n";
00317 Sfile.close();
00318 }
00319
00320 void Space::clearBoxes (void)
00321 {
00322
00323 for (b_it i=b.begin();i!=b.end();i++) {i->clearFaces();}
00324 }
00325
00326 void Space::recordFace (vec_bp & ptr,Face * const f)
00327 {
00328
00329 for (bp_it i=ptr.begin();i!=ptr.end();i++) {(*i)->addFace(f);}
00330 }
00331
00332 void Space::getSearchRadius (double * const sr,int const * const indices) const
00333 {
00334
00335 sr[0] = indices[0]*SPACE_LENGTH*SCALE+world[0];
00336 sr[1] = (indices[1]+1)*SPACE_LENGTH*SCALE+world[0];
00337 sr[2] = indices[2]*SPACE_LENGTH*SCALE+world[2];
00338 sr[3] = (indices[3]+1)*SPACE_LENGTH*SCALE+world[2];
00339 sr[4] = indices[4]*SPACE_LENGTH*SCALE+world[4];
00340 sr[5] = (indices[5]+1)*SPACE_LENGTH*SCALE+world[4];
00341 }
00342
00343 bool Space::expandSearchRadius (bool const gate,double const cd,double const * const pd,int * const inc,int * const indices) const
00344 {
00345 bool reanalyze = false;
00346 const char key[7] = "xxyyzz";
00347 char single[1];
00348 int val[6] = {-1,1,-1,1,-1,1};
00349
00350
00351
00352 for(int j=0;j<6;j++)
00353 {
00354
00355 if( (inc[j]<NUM_ADJACENT_BOXES) && ((gate==false) || (cd>pd[j])))
00356 {
00357
00358 sprintf(single,"%c",key[j]);
00359 int i = screenIndex(indices[j]+val[j],single);
00360 if(i!=indices[j])
00361 {
00362 indices[j] = i;
00363 inc[j]++;
00364 reanalyze = true;
00365 }
00366 else
00367 {
00368 inc[j]=NUM_ADJACENT_BOXES;
00369 }
00370 }
00371 }
00372
00373 return reanalyze;
00374 }
00375
00376 double Space::getWorld (int i) const
00377 {
00378 return world[i];
00379 }
00380
00381 b_cit Space::begin (void) const
00382 {
00383 return b.begin();
00384 }
00385
00386 b_cit Space::end (void) const
00387 {
00388 return b.end();
00389 }
00390
00391 Box * Space::getBox (int i)
00392 {
00393 return &b[i];
00394 }
00395