space.cc

Go to the documentation of this file.
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   // Not thread-safe.
00022   // -- lock mutex
00023   if (only_one == NULL)
00024     only_one = new Space();
00025   // -- unlock mutex
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   // assume p = [xmin,xmax,ymin,ymax,zmin,zmax]
00072   int br[6];
00073   // compute 3D index range that includes 3D location range
00074   br[0] = location2Index(origin[0],"x");   // -x
00075   br[1] = location2Index(   eend[0],"x");       //  x
00076   br[2] = location2Index(origin[1],"y");        // -y
00077   br[3] = location2Index(   eend[1],"y");       //  y
00078   br[4] = location2Index(origin[2],"z");   // -z
00079   br[5] = location2Index(   eend[2],"z");       //  z
00080   // collect boxes to check
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   // do not assume br = [xmin,xmax,ymin,ymax,zmin,zmax]
00088   // instead assume br = [x1,x2,y1,y2,z1,z2]
00089   // and identify smallest and largest here
00090 
00091   // new
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   // old 
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   // since world[] is calculated only once, face limits may be less than world[0,2,4]
00177   // and greater than world[1,3,5]. Consequently, box_range as computed above may
00178   // yield negative indices or indices beyond declared range, respectively.
00179   // Therefore, constrain box_range to known index range.
00180   // Effectively, border boxes are understood to extend to infinity
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   // subdivide space
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   // allocate memory for boxes
00214   b.reserve(axes[0]*axes[1]*axes[2]);
00215   // store box limits in boxes class
00216   // for each box
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   //initialize mins and maxes
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   // for each object
00241   for (o_cit i=Container::instance().o.begin();i!=Container::instance().o.end();i++)
00242   {
00243     // get range of object vertices
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   // identify face bounding box limits
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   // grab face 3D location range
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   // collect boxes to check
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   // for each box in space, clear vector of face*
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   // for each box, add face
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   // [xmin xmax ymin ymax zmin zmax]
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   // if cp was found
00350   //if(gate==true)
00351   //{
00352     for(int j=0;j<6;j++)
00353     {
00354       // expand sr in each direction if needed and allowed
00355       if( (inc[j]<NUM_ADJACENT_BOXES) && ((gate==false) || (cd>pd[j])))
00356       {
00357         // expand sr in -x direction
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 

Generated on Fri Jul 18 19:43:40 2008 for meshmorph by  doxygen 1.5.1