SpatialGridContainer.inl

Go to the documentation of this file.
00001 /******************************************************************************
00002 *       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3      *
00003 *                (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS                    *
00004 *                                                                             *
00005 * This library is free software; you can redistribute it and/or modify it     *
00006 * under the terms of the GNU Lesser General Public License as published by    *
00007 * the Free Software Foundation; either version 2.1 of the License, or (at     *
00008 * your option) any later version.                                             *
00009 *                                                                             *
00010 * This library is distributed in the hope that it will be useful, but WITHOUT *
00011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
00012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
00013 * for more details.                                                           *
00014 *                                                                             *
00015 * You should have received a copy of the GNU Lesser General Public License    *
00016 * along with this library; if not, write to the Free Software Foundation,     *
00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
00018 *******************************************************************************
00019 *                               SOFA :: Modules                               *
00020 *                                                                             *
00021 * Authors: The SOFA Team and external contributors (see Authors.txt)          *
00022 *                                                                             *
00023 * Contact information: contact@sofa-framework.org                             *
00024 ******************************************************************************/
00025 //
00026 // C++ Interface: SpatialGridContainer
00027 //
00028 // Description: 
00029 //
00030 //
00031 // Author: The SOFA team <http://www.sofa-framework.org>, (C) 2006
00032 //
00033 // Copyright: See COPYING file that comes with this distribution
00034 //
00035 //
00036 
00037 #ifndef SOFA_COMPONENT_CONTAINER_SPATIALGRIDCONTAINER_INL
00038 #define SOFA_COMPONENT_CONTAINER_SPATIALGRIDCONTAINER_INL
00039 
00040 #include <sofa/component/container/SpatialGridContainer.h>
00041 
00042 #include <sofa/component/topology/PointSetTopologyChange.h>
00043 #include <sofa/component/topology/PointSetTopologyModifier.h>
00044 
00045 #include <sofa/simulation/common/AnimateBeginEvent.h>
00046 #include <sofa/simulation/common/AnimateEndEvent.h>
00047 #include <sofa/helper/system/gl.h>
00048 #include <sofa/component/MechanicalObject.h>
00049 
00050 
00051 namespace sofa
00052 {
00053 
00054 namespace component
00055 {
00056 
00057 namespace container
00058 {
00059 
00060       using namespace sofa::helper;
00061 
00062       template<class DataTypes>
00063       typename SpatialGrid<DataTypes>::Grid SpatialGrid<DataTypes>::emptyGrid;
00064 
00065       template<class DataTypes>
00066       SpatialGrid<DataTypes>::SpatialGrid(Real cellWidth)
00067   : cellWidth(cellWidth), invCellWidth(1/cellWidth)
00068       {
00069       }
00070 
00071       template<class DataTypes>
00072       const typename SpatialGrid<DataTypes>::Grid* SpatialGrid<DataTypes>::findGrid(const Key& k) const
00073       {
00074     typename Map::const_iterator it = map.find(k);
00075     if (it == map.end()) return &emptyGrid;
00076     else return it->second;
00077       }
00078 
00079       template<class DataTypes>
00080       typename SpatialGrid<DataTypes>::Grid* SpatialGrid<DataTypes>::getGrid(const Key& k)
00081       {
00082     Grid* & g = map[k];
00083     if (g == NULL)
00084       {
00085         g = new Grid;
00086         Grid* g2;
00087         typename Map::const_iterator it;
00088         typename Map::const_iterator end = map.end();
00089         it = map.find(Key(k[0]-1, k[1]  , k[2]  ));
00090         if (it != end)
00091           {
00092         g2 = it->second;
00093         g->neighbors[0] = g2; g2->neighbors[1] = g;
00094           }
00095         else
00096           g->neighbors[0] = &emptyGrid;
00097         it = map.find(Key(k[0]+1, k[1]  , k[2]  ));
00098         if (it != end)
00099           {
00100         g2 = it->second;
00101         g->neighbors[1] = g2; g2->neighbors[0] = g;
00102           }
00103         else
00104           g->neighbors[1] = &emptyGrid;
00105         it = map.find(Key(k[0]  , k[1]-1, k[2]  ));
00106         if (it != end)
00107           {
00108         g2 = it->second;
00109         g->neighbors[2] = g2; g2->neighbors[3] = g;
00110           }
00111         else
00112           g->neighbors[2] = &emptyGrid;
00113         it = map.find(Key(k[0]  , k[1]+1, k[2]  ));
00114         if (it != end)
00115           {
00116         g2 = it->second;
00117         g->neighbors[3] = g2; g2->neighbors[2] = g;
00118           }
00119         else
00120           g->neighbors[3] = &emptyGrid;
00121         it = map.find(Key(k[0]  , k[1]  , k[2]-1));
00122         if (it != end)
00123           {
00124         g2 = it->second;
00125         g->neighbors[4] = g2; g2->neighbors[5] = g;
00126           }
00127         else
00128           g->neighbors[4] = &emptyGrid;
00129         it = map.find(Key(k[0]  , k[1]  , k[2]+1));
00130         if (it != end)
00131           {
00132         g2 = it->second;
00133         g->neighbors[5] = g2; g2->neighbors[4] = g;
00134           }
00135         else
00136           g->neighbors[5] = &emptyGrid;
00137       }
00138     return g;
00139       }
00140 
00141       template<class DataTypes>
00142       typename SpatialGrid<DataTypes>::Cell* SpatialGrid<DataTypes>::getCell(const Coord& x)
00143       {
00144     int ix = rfloor(x[0]*invCellWidth);
00145     int iy = rfloor(x[1]*invCellWidth);
00146     int iz = rfloor(x[2]*invCellWidth);
00147     Key k(ix >> GRIDDIM_LOG2, iy >> GRIDDIM_LOG2, iz >> GRIDDIM_LOG2);
00148     ix &= GRIDDIM-1;
00149     iy &= GRIDDIM-1;
00150     iz &= GRIDDIM-1;
00151     Grid* g = getGrid(k);
00152     return g->cell+(ix+GRIDDIM*iy+GRIDDIM*GRIDDIM*iz);
00153       }
00154 
00155       template<class DataTypes>
00156       const typename SpatialGrid<DataTypes>::Cell* SpatialGrid<DataTypes>::getCell(const Grid* g, int x, int y, int z)
00157       {
00158     if (x<0)
00159       {
00160         g = g->neighbors[0];
00161         x += GRIDDIM;
00162       }
00163     else if (x >= GRIDDIM)
00164       {
00165         g = g->neighbors[1];
00166         x -= GRIDDIM;
00167       }
00168     if (y<0)
00169       {
00170         g = g->neighbors[2];
00171         y += GRIDDIM;
00172       }
00173     else if (y >= GRIDDIM)
00174       {
00175         g = g->neighbors[3];
00176         y -= GRIDDIM;
00177       }
00178     if (z<0)
00179       {
00180         g = g->neighbors[4];
00181         z += GRIDDIM;
00182       }
00183     else if (z >= GRIDDIM)
00184       {
00185         g = g->neighbors[5];
00186         z -= GRIDDIM;
00187       }
00188     return g->cell + (x*DX + y*DY + z*DZ);
00189       }
00190 
00191       template<class DataTypes> template<class NeighborListener>
00192       void SpatialGrid<DataTypes>::findNeighbors(NeighborListener* dest, const Real dist2, const Cell** cellsBegin, const Cell** cellsEnd)
00193       {
00194     const Cell* c0 = *cellsBegin;
00195     const typename std::list<Entry>::const_iterator end = c0->plist.end();
00196     for (typename std::list<Entry>::const_iterator it = c0->plist.begin(); it != end; it++)
00197       {
00198         const Entry& p1 = *it;
00199         typename std::list<Entry>::const_iterator it2 = it;
00200         ++it2;
00201         for (; it2 != end; it2++)
00202           {
00203         const Entry& p2 = *it2;
00204         const Real r2 = (p2.pos - p1.pos).norm2();
00205         if (r2 < dist2)
00206           dest->addNeighbor(p1.index, p2.index, r2, dist2);
00207           }
00208         for (const Cell** c = cellsBegin+1; c != cellsEnd; ++c)
00209           {
00210         const typename std::list<Entry>::const_iterator end2 = (*c)->plist.end();
00211         for (typename std::list<Entry>::const_iterator it2 = (*c)->plist.begin(); it2 != end2; it2++)
00212           {
00213             const Entry& p2 = *it2;
00214             const Real r2 = (p2.pos - p1.pos).norm2();
00215             if (r2 < dist2)
00216               {
00217             dest->addNeighbor(p1.index, p2.index, r2, dist2);
00218               }
00219           }
00220           }
00221       }
00222       }
00223 
00224 template<class DataTypes> template<class NeighborListener>
00225       void SpatialGrid<DataTypes>::findNeighbors(NeighborListener* dest, Real dist)
00226       {
00227     const Real dist2 = dist*dist;
00228     for (typename Map::iterator itg = map.begin();itg != map.end(); itg++)
00229       {
00230         Grid* g = itg->second;
00231         if (g->empty) continue;
00232         const Cell* cell[14];
00233         int ic = 0;
00234         int x,y,z;
00235         cell[0] = g->cell;
00236         for (z = 0; z<GRIDDIM; z++)
00237           {
00238         for (y = 0; y<GRIDDIM; y++)
00239           {
00240             cell[ 0] = g->cell+ic;
00241             cell[ 2] = getCell(g,  0, y+1, z  );
00242             cell[ 4] = getCell(g,  0, y  , z+1); //(z < GRIDDIM-1) ? g->cell+(ic + DZ) : g->neighbors[5]->cell+(ic - (GRIDDIM-1)*DZ);
00243             cell[ 6] = getCell(g,  0, y+1, z+1); //(y < GRIDDIM-1) ? cell[4] + DY : (z < GRIDDIM-1) ? cell[2] + DZ : g->neighbors[3]->neighbors[5]->cell+(ic - (GRIDDIM-1)*(DY+DZ));
00244             cell[ 8] = getCell(g, -1, y+1, z  ); //(y < GRIDDIM-1) ? g->neighbors[0]->cell+(ic - (GRIDDIM-1)*DX + DY) : g->neighbors[0]->neighbors[3]->cell+(ic - (GRIDDIM-1)*(DX+DY));
00245             cell[ 9] = getCell(g, -1, y  , z+1); //(z < GRIDDIM-1) ? g->neighbors[0]->cell+(ic - (GRIDDIM-1)*DX + DZ) : g->neighbors[0]->neighbors[5]->cell+(ic - (GRIDDIM-1)*(DX+DZ));
00246             cell[10] = getCell(g, -1, y+1, z+1); //(y < GRIDDIM-1) ? cell[9] + DY : (z < GRIDDIM-1) ? cell[8] + DZ : g->neighbors[0]->neighbors[3]->neighbors[5]->cell+(ic - (GRIDDIM-1)*(DX+DY+DZ));
00247             cell[11] = getCell(g, -1, y-1, z+1); //(y > 0) ? cell[9] - DY : (z < GRIDDIM-1) ? cell[8] + DZ : g->neighbors[0]->neighbors[3]->neighbors[5]->cell+(ic - (GRIDDIM-1)*(DX+DY+DZ));
00248             cell[12] = getCell(g,  0, y-1, z+1);
00249             for (x = 0; x<GRIDDIM-1; x++)
00250               {
00251             cell[ 1] = cell[ 0] + DX;
00252             cell[ 3] = cell[ 2] + DX;
00253             cell[ 5] = cell[ 4] + DX;
00254             cell[ 7] = cell[ 6] + DX;
00255             cell[13] = cell[12] + DX;
00256             if (!cell[0]->plist.empty())
00257               this->findNeighbors(dest, dist2, cell, cell+14);
00258             cell[ 8] = cell[ 2];
00259             cell[ 9] = cell[ 4];
00260             cell[10] = cell[ 6];
00261             cell[11] = cell[12];
00262             cell[12] = cell[13];
00263             cell[ 0] = cell[ 1];
00264             cell[ 2] = cell[ 3];
00265             cell[ 4] = cell[ 5];
00266             cell[ 6] = cell[ 7];
00267             ++ic;
00268               }
00269             if (!cell[0]->plist.empty())
00270               {
00271             cell[ 1] = g->neighbors[1]->cell+(ic - (GRIDDIM-1)*DX);
00272             cell[ 3] = getCell(g, GRIDDIM, y+1, z  ); //(y < GRIDDIM-1) ? cell[1] + DY : g->neighbors[3]->cell+(ic - (GRIDDIM-1)*(DX+DY));
00273             cell[ 5] = getCell(g, GRIDDIM, y  , z+1); //(z < GRIDDIM-1) ? cell[1] + DZ : g->neighbors[5]->cell+(ic - (GRIDDIM-1)*(DX+DZ));
00274             cell[ 7] = getCell(g, GRIDDIM, y+1, z+1); //(y < GRIDDIM-1) ? cell[5] + DY : (z < GRIDDIM-1) ? cell[3] + DZ : g->neighbors[3]->neighbors[5]->cell+(ic - (GRIDDIM-1)*(DX+DY+DZ));
00275             cell[13] = getCell(g, GRIDDIM, y-1, z+1); //cell[12] + DX;
00276             this->findNeighbors(dest, dist2, cell, cell+14);
00277               }
00278             ++ic;
00279           }
00280           }
00281       }
00282       }
00283 
00284       template<class DataTypes>
00285       void SpatialGrid<DataTypes>::computeField(ParticleField* field, Real dist)
00286       {
00287     //dist /= cellWidth;
00288     const Real dist2 = dist*dist;
00289     const int r = rceil(dist/cellWidth)+1;
00290     int x,y,z;
00291     int x2,y2,z2;
00292     if (r > GRIDDIM)
00293       {
00294         std::cerr << "Distance too large in SpatialGrid::computeField ("<<r<<" > "<<GRIDDIM<<")\n";
00295         return;
00296       }
00297     //std::cout << "accumulate particles with radius "<<dist<<std::endl;
00298     for (typename Map::iterator itg = map.begin();itg != map.end(); itg++)
00299       {
00300         Grid* g = itg->second;
00301         Coord pos;
00302         pos[0] = (Real)(itg->first[0]*GRIDDIM);
00303         pos[1] = (Real)(itg->first[1]*GRIDDIM);
00304         pos[2] = (Real)(itg->first[2]*GRIDDIM);
00305         if (!g->empty)
00306           {
00307         Cell* c;
00308         Cell* c2;
00309         for (z = 0, c = g->cell; z<GRIDDIM; z++)
00310           {
00311             int z0 = (z<r)?0:z-r+1;
00312             int z1 = (z>GRIDDIM-1-r)?GRIDDIM-1:z+r;
00313             for (y = 0; y<GRIDDIM; y++)
00314               {
00315             int y0 = (y<r)?0:y-r+1;
00316             int y1 = (y>GRIDDIM-1-r)?GRIDDIM-1:y+r;
00317             for (x = 0; x<GRIDDIM; x++, c++)
00318               {
00319                 if (!c->plist.empty())
00320                   {
00321                 int x0 = (x<r)?0:x-r+1;
00322                 int x1 = (x>GRIDDIM-1-r)?GRIDDIM-1:x+r;
00323                 typename std::list<Entry>::const_iterator begin = c->plist.begin();
00324                 typename std::list<Entry>::const_iterator end = c->plist.end();
00325                 typename std::list<Entry>::const_iterator it;
00326                 //std::cout << "accumulate "<<c->plist.size()<<" particles from <"<<pos<<">+<"<<x<<" "<<y<<" "<<z<<"> to area <"<<x0<<" "<<y0<<" "<<z0<<">-<"<<x1<<" "<<y1<<" "<<z1<<">"<<std::endl;
00327                 c2 = g->cell+(x0*DX+y0*DY+z0*DZ);
00328                 const int dy = DY-(x1-x0+1)*DX;
00329                 const int dz = DZ-(y1-y0+1)*DY;
00330                 Coord p;
00331                 for (z2 = z0; z2<=z1; z2++, c2+=dz)
00332                   {
00333                     p[2] = (pos[2]+z2)*cellWidth;
00334                     for (y2 = y0; y2<=y1; y2++, c2+=dy)
00335                       {
00336                     p[1] = (pos[1]+y2)*cellWidth;
00337                     for (x2 = x0; x2<=x1; x2++, c2+=DX)
00338                       {
00339                         p[0] = (pos[0]+x2)*cellWidth;
00340                         for (it=begin; it != end; ++it)
00341                           {
00342                         Real r2 = (it->pos-p).norm2();
00343                         if (r2 < dist2)
00344                           c2->data.add(field, it->index, r2, dist2);
00345                           }
00346                       }
00347                       }
00348                   }
00349                   }
00350               }
00351               }
00352           }
00353           }
00354         for (int gz=-1; gz<=1; gz++)
00355           {
00356         for (int gy=-1; gy<=1; gy++)
00357           {
00358             for (int gx=-1; gx<=1; gx++)
00359               {
00360             const Grid* g2 = g;
00361             if (gx==-1) g2 = g2->neighbors[0]; else if (gx==1) g2 = g2->neighbors[1];
00362             if (gy==-1) g2 = g2->neighbors[2]; else if (gy==1) g2 = g2->neighbors[3];
00363             if (gz==-1) g2 = g2->neighbors[4]; else if (gz==1) g2 = g2->neighbors[5];
00364             if (g2 == g) continue;
00365             if (!g2->empty)
00366               {
00367                 int g2_x0 = 0, g2_x1 = GRIDDIM-1; //, g_x0 = 0, g_x1 = GRIDDIM-1, g_dx0 = 0, g_dx1 = 0;
00368                 int g2_y0 = 0, g2_y1 = GRIDDIM-1; //, g_y0 = 0, g_y1 = GRIDDIM-1, g_dy0 = 0, g_dy1 = 0;
00369                 int g2_z0 = 0, g2_z1 = GRIDDIM-1; //, g_z0 = 0, g_z1 = GRIDDIM-1, g_dz0 = 0, g_dz1 = 0;
00370                         
00371                 if (gx<0)      { g2_x0 = GRIDDIM-r; } // g_x1 = 0;  g_dx1 = 1; }
00372                 else if (gx>0) { g2_x1 = r-1; } // g_x0 = GRIDDIM-r;  g_dx0 = 1; }
00373                         
00374                 if (gy<0)      { g2_y0 = GRIDDIM-r; } // g_y1 = 0;  g_dy1 = 1; }
00375                 else if (gy>0) { g2_y1 = r-1; } // g_y0 = GRIDDIM-r;  g_dy0 = 1; }
00376                         
00377                 if (gz<0)      { g2_z0 = GRIDDIM-r; } // g_z1 = 0;  g_dz1 = 1; }
00378                 else if (gz>0) { g2_z1 = r-1; } // g_z0 = GRIDDIM-r;  g_dz0 = 1; }
00379                         
00380                 //std::cout << "accumulate neighbors particles from <"<<g2_x0<<" "<<g2_y0<<" "<<g2_z0<<">-<"<<g2_x1<<" "<<g2_y1<<" "<<g2_z1<<">"<<std::endl;
00381                 //int z0 = g_z0;
00382                 //int z1 = g_z1;
00383                 const Cell* cz = g2->cell+(g2_x0*DX+g2_y0*DY+g2_z0*DZ);
00384                 for (z = g2_z0; z<=g2_z1; z++, cz+=DZ) //, z0+=g_dx0, z1+=g_dx1)
00385                   {
00386                 //int y0 = g_y0;
00387                 //int y1 = g_y1;
00388                 const Cell* cy = cz;
00389                 for (y = g2_y0; y<=g2_y1; y++, cy+=DY) //, y0+=g_dy0, y1+=g_dy1)
00390                   {
00391                     //int x0 = g_x0;
00392                     //int x1 = g_x1;
00393                     const Cell* c = cy;
00394                     for (x = g2_x0; x<=g2_x1; x++, c++) //, x0+=g_dx0, x1+=g_dx1)
00395                       {
00396                     if (!c->plist.empty())
00397                       {
00398                         typename std::list<Entry>::const_iterator begin = c->plist.begin();
00399                         typename std::list<Entry>::const_iterator end = c->plist.end();
00400                         typename std::list<Entry>::const_iterator it;
00401                         int x0 = x + gx*GRIDDIM - r+1; if (x0<0) x0 = 0;
00402                         int x1 = x + gx*GRIDDIM + r; if (x1>GRIDDIM-1) x1 = GRIDDIM-1;
00403                         int y0 = y + gy*GRIDDIM - r+1; if (y0<0) y0 = 0;
00404                         int y1 = y + gy*GRIDDIM + r; if (y1>GRIDDIM-1) y1 = GRIDDIM-1;
00405                         int z0 = z + gz*GRIDDIM - r+1; if (z0<0) z0 = 0;
00406                         int z1 = z + gz*GRIDDIM + r; if (z1>GRIDDIM-1) z1 = GRIDDIM-1;
00407                         //std::cout << "accumulate neighbors "<<c->plist.size()<<" particles from <"<<pos<<">+<"<<x+gx*GRIDDIM<<" "<<y+gy*GRIDDIM<<" "<<z+gz*GRIDDIM<<"> to area <"<<x0<<" "<<y0<<" "<<z0<<">-<"<<x1<<" "<<y1<<" "<<z1<<">"<<std::endl;
00408                         Cell* c2 = g->cell+(x0*DX+y0*DY+z0*DZ);
00409                         const int dy = DY-(x1-x0+1)*DX;
00410                         const int dz = DZ-(y1-y0+1)*DY;
00411                         Coord p;
00412                         for (z2 = z0; z2<=z1; z2++, c2+=dz)
00413                           {
00414                         p[2] = (pos[2]+z2)*cellWidth;
00415                         for (y2 = y0; y2<=y1; y2++, c2+=dy)
00416                           {
00417                             p[1] = (pos[1]+y2)*cellWidth;
00418                             for (x2 = x0; x2<=x1; x2++, c2+=DX)
00419                               {
00420                             p[0] = (pos[0]+x2)*cellWidth;
00421                             for (it=begin; it != end; ++it)
00422                               {
00423                                 Real r2 = (it->pos-p).norm2();
00424                                 if (r2 < dist2)
00425                                   c2->data.add(field, it->index, r2, dist2);
00426                               }
00427                               }
00428                           }
00429                           }
00430                       }
00431                       }
00432                   }
00433                   }
00434               }
00435               }
00436           }
00437           }
00438       }
00439       }
00440 
00441       template<class DataTypes>
00442       void SpatialGrid<DataTypes>::begin()
00443       {
00444     for (typename Map::iterator itg = map.begin();itg != map.end(); itg++)
00445       {
00446         Grid* g = itg->second;
00447         //g->clear();
00448         delete g;
00449       }
00450     map.clear();
00451       }
00452 
00453       template<class DataTypes>
00454       void SpatialGrid<DataTypes>::add(int i, const Coord& pos, bool allNeighbors)
00455       {
00456     int ix = rfloor(pos[0]*invCellWidth);
00457     int iy = rfloor(pos[1]*invCellWidth);
00458     int iz = rfloor(pos[2]*invCellWidth);
00459     Key k(ix >> GRIDDIM_LOG2, iy >> GRIDDIM_LOG2, iz >> GRIDDIM_LOG2);
00460     ix &= GRIDDIM-1;
00461     iy &= GRIDDIM-1;
00462     iz &= GRIDDIM-1;
00463     Grid* g = getGrid(k);
00464     if (g->empty)
00465       {
00466         g->empty = false;
00467         // create direct neighbor grids
00468         if (g->neighbors[0] == &emptyGrid) getGrid(Key(k[0]-1, k[1]  , k[2]  ));
00469         if (g->neighbors[1] == &emptyGrid) getGrid(Key(k[0]+1, k[1]  , k[2]  ));
00470         if (g->neighbors[2] == &emptyGrid) getGrid(Key(k[0]  , k[1]-1, k[2]  ));
00471         if (g->neighbors[3] == &emptyGrid) getGrid(Key(k[0]  , k[1]+1, k[2]  ));
00472         if (g->neighbors[4] == &emptyGrid) getGrid(Key(k[0]  , k[1]  , k[2]-1));
00473         if (g->neighbors[5] == &emptyGrid) getGrid(Key(k[0]  , k[1]  , k[2]+1));
00474         if (allNeighbors)
00475           {   // create all 26 neighbors
00476         if (g->neighbors[0]->neighbors[2] == &emptyGrid) getGrid(Key(k[0]-1, k[1]-1, k[2]  ));
00477         if (g->neighbors[1]->neighbors[2] == &emptyGrid) getGrid(Key(k[0]+1, k[1]-1, k[2]  ));
00478         if (g->neighbors[0]->neighbors[3] == &emptyGrid) getGrid(Key(k[0]-1, k[1]+1, k[2]  ));
00479         if (g->neighbors[1]->neighbors[3] == &emptyGrid) getGrid(Key(k[0]+1, k[1]+1, k[2]  ));
00480         if (g->neighbors[0]->neighbors[4] == &emptyGrid) getGrid(Key(k[0]-1, k[1]  , k[2]-1));
00481         if (g->neighbors[1]->neighbors[4] == &emptyGrid) getGrid(Key(k[0]+1, k[1]  , k[2]-1));
00482         if (g->neighbors[0]->neighbors[5] == &emptyGrid) getGrid(Key(k[0]-1, k[1]  , k[2]+1));
00483         if (g->neighbors[1]->neighbors[5] == &emptyGrid) getGrid(Key(k[0]+1, k[1]  , k[2]+1));
00484         if (g->neighbors[2]->neighbors[4] == &emptyGrid) getGrid(Key(k[0]  , k[1]-1, k[2]-1));
00485         if (g->neighbors[3]->neighbors[4] == &emptyGrid) getGrid(Key(k[0]  , k[1]+1, k[2]-1));
00486         if (g->neighbors[2]->neighbors[5] == &emptyGrid) getGrid(Key(k[0]  , k[1]-1, k[2]+1));
00487         if (g->neighbors[3]->neighbors[5] == &emptyGrid) getGrid(Key(k[0]  , k[1]+1, k[2]+1));
00488 
00489         if (g->neighbors[0]->neighbors[2]->neighbors[4] == &emptyGrid) getGrid(Key(k[0]-1, k[1]-1, k[2]-1));
00490         if (g->neighbors[1]->neighbors[2]->neighbors[4] == &emptyGrid) getGrid(Key(k[0]+1, k[1]-1, k[2]-1));
00491         if (g->neighbors[0]->neighbors[3]->neighbors[4] == &emptyGrid) getGrid(Key(k[0]-1, k[1]+1, k[2]-1));
00492         if (g->neighbors[1]->neighbors[3]->neighbors[4] == &emptyGrid) getGrid(Key(k[0]+1, k[1]+1, k[2]-1));
00493         if (g->neighbors[0]->neighbors[2]->neighbors[5] == &emptyGrid) getGrid(Key(k[0]-1, k[1]-1, k[2]+1));
00494         if (g->neighbors[1]->neighbors[2]->neighbors[5] == &emptyGrid) getGrid(Key(k[0]+1, k[1]-1, k[2]+1));
00495         if (g->neighbors[0]->neighbors[3]->neighbors[5] == &emptyGrid) getGrid(Key(k[0]-1, k[1]+1, k[2]+1));
00496         if (g->neighbors[1]->neighbors[3]->neighbors[5] == &emptyGrid) getGrid(Key(k[0]+1, k[1]+1, k[2]+1));
00497           }
00498       }
00499     g->cell[ix+GRIDDIM*iy+GRIDDIM*GRIDDIM*iz].plist.push_back(Entry(i,pos));
00500       }
00501 
00502       template<class DataTypes>
00503       void SpatialGrid<DataTypes>::end()
00504       {
00505     //for (typename Map::iterator itg = map.begin();itg != map.end(); itg++)
00506     //{
00507     //  const Key& k = itg->first;
00508     //  Grid* g = itg->second;
00509     //  g->neighbors[0] = g;
00510     //  for (int i=1;i<8;i++)
00511     //  {
00512     //      g->neighbors[i] = findGrid(Key(k[0]+(i&1),k[1]+((i>>1)&1),k[2]+((i>>2)&1)));
00513     //  }
00514     //  g->neighbors[ 8] = findGrid(Key(k[0]-1,k[1]+1,k[2]  ));
00515     //  g->neighbors[ 9] = findGrid(Key(k[0]-1,k[1]  ,k[2]+1));
00516     //  g->neighbors[10] = findGrid(Key(k[0]-1,k[1]+1,k[2]+1));
00517     //  g->neighbors[11] = findGrid(Key(k[0]-1,k[1]-1,k[2]+1));
00518     //  g->neighbors[12] = findGrid(Key(k[0]  ,k[1]-1,k[2]+1));
00519     //  g->neighbors[13] = findGrid(Key(k[0]+1,k[1]-1,k[2]+1));
00520     //}
00521       }
00522 
00526 template<class DataTypes>
00527 void SpatialGrid<DataTypes>::reorderIndices(helper::vector<unsigned int>* old2new, helper::vector<unsigned int>* new2old)
00528 {
00529     unsigned int next = 0;
00530     for (typename Map::iterator itg = map.begin();itg != map.end(); itg++)
00531     {
00532     Key k = itg->first;
00533     Grid* g = itg->second;
00534     if (g->empty) continue;
00535     for (int i=0; i<NCELL; ++i)
00536     {
00537         int j=0;
00538         for (int s=0;s<GRIDDIM_LOG2;++s)
00539         for(int c=0;c<3;++c)
00540             j += ((i>>(3*s+c))&1)<<(GRIDDIM_LOG2*c+s);
00541         Cell* c = g->cell+j;
00542         for (typename std::list<Entry>::iterator it = c->plist.begin(), itend = c->plist.end(); it != itend; ++it)
00543         {
00544         unsigned int old = it->index;
00545         if (old2new != NULL)
00546         {
00547             if (old >= old2new->size()) old2new->resize(old+1);
00548             (*old2new)[old] = next;
00549         }
00550         if (new2old != NULL)
00551         {
00552             if (next >= new2old->size()) new2old->resize(next+1);
00553             (*new2old)[next] = old;
00554         }
00555         it->index = next;
00556         ++next;
00557         }
00558     }
00559     }
00560 }
00561 
00562       template<class DataTypes>
00563       void SpatialGrid<DataTypes>::draw()
00564       {
00565     const float cscale = (float)(cellWidth);
00566     const float gscale = (float)(cellWidth*GRIDDIM);
00567     glBegin(GL_LINES);
00568     for (typename Map::iterator itg = map.begin();itg != map.end(); itg++)
00569       {
00570         Key k = itg->first;
00571         Grid* g = itg->second;
00572         glColor3f(1,1,1);
00573         glVertex3f((k[0]  )*gscale, (k[1]  )*gscale, (k[2]  )*gscale);
00574         glVertex3f((k[0]+1)*gscale, (k[1]  )*gscale, (k[2]  )*gscale);
00575         glVertex3f((k[0]  )*gscale, (k[1]+1)*gscale, (k[2]  )*gscale);
00576         glVertex3f((k[0]+1)*gscale, (k[1]+1)*gscale, (k[2]  )*gscale);
00577         glVertex3f((k[0]  )*gscale, (k[1]  )*gscale, (k[2]+1)*gscale);
00578         glVertex3f((k[0]+1)*gscale, (k[1]  )*gscale, (k[2]+1)*gscale);
00579         glVertex3f((k[0]  )*gscale, (k[1]+1)*gscale, (k[2]+1)*gscale);
00580         glVertex3f((k[0]+1)*gscale, (k[1]+1)*gscale, (k[2]+1)*gscale);
00581 
00582         glVertex3f((k[0]  )*gscale, (k[1]  )*gscale, (k[2]  )*gscale);
00583         glVertex3f((k[0]  )*gscale, (k[1]+1)*gscale, (k[2]  )*gscale);
00584         glVertex3f((k[0]+1)*gscale, (k[1]  )*gscale, (k[2]  )*gscale);
00585         glVertex3f((k[0]+1)*gscale, (k[1]+1)*gscale, (k[2]  )*gscale);
00586         glVertex3f((k[0]  )*gscale, (k[1]  )*gscale, (k[2]+1)*gscale);
00587         glVertex3f((k[0]  )*gscale, (k[1]+1)*gscale, (k[2]+1)*gscale);
00588         glVertex3f((k[0]+1)*gscale, (k[1]  )*gscale, (k[2]+1)*gscale);
00589         glVertex3f((k[0]+1)*gscale, (k[1]+1)*gscale, (k[2]+1)*gscale);
00590 
00591         glVertex3f((k[0]  )*gscale, (k[1]  )*gscale, (k[2]  )*gscale);
00592         glVertex3f((k[0]  )*gscale, (k[1]  )*gscale, (k[2]+1)*gscale);
00593         glVertex3f((k[0]  )*gscale, (k[1]+1)*gscale, (k[2]  )*gscale);
00594         glVertex3f((k[0]  )*gscale, (k[1]+1)*gscale, (k[2]+1)*gscale);
00595         glVertex3f((k[0]+1)*gscale, (k[1]  )*gscale, (k[2]  )*gscale);
00596         glVertex3f((k[0]+1)*gscale, (k[1]  )*gscale, (k[2]+1)*gscale);
00597         glVertex3f((k[0]+1)*gscale, (k[1]+1)*gscale, (k[2]  )*gscale);
00598         glVertex3f((k[0]+1)*gscale, (k[1]+1)*gscale, (k[2]+1)*gscale);
00599 
00600         if (g->neighbors[0] == &emptyGrid)
00601           {
00602         glColor3f(1.0f,0.0f,0.0f);
00603         glVertex3f((k[0]     )*gscale, (k[1]+0.3f)*gscale, (k[2]+0.3f)*gscale);
00604         glVertex3f((k[0]     )*gscale, (k[1]+0.7f)*gscale, (k[2]+0.7f)*gscale);
00605         glVertex3f((k[0]     )*gscale, (k[1]+0.3f)*gscale, (k[2]+0.7f)*gscale);
00606         glVertex3f((k[0]     )*gscale, (k[1]+0.7f)*gscale, (k[2]+0.3f)*gscale);
00607           }
00608         if (g->neighbors[1] == &emptyGrid)
00609           {
00610         glColor3f(1.0f,0.5f,0.5f);
00611         glVertex3f((k[0]+1   )*gscale, (k[1]+0.3f)*gscale, (k[2]+0.3f)*gscale);
00612         glVertex3f((k[0]+1   )*gscale, (k[1]+0.7f)*gscale, (k[2]+0.7f)*gscale);
00613         glVertex3f((k[0]+1   )*gscale, (k[1]+0.3f)*gscale, (k[2]+0.7f)*gscale);
00614         glVertex3f((k[0]+1   )*gscale, (k[1]+0.7f)*gscale, (k[2]+0.3f)*gscale);
00615           }
00616         if (g->neighbors[2] == &emptyGrid)
00617           {
00618         glColor3f(0.0f,1.0f,0.0f);
00619         glVertex3f((k[0]+0.3f)*gscale, (k[1]     )*gscale, (k[2]+0.3f)*gscale);
00620         glVertex3f((k[0]+0.7f)*gscale, (k[1]     )*gscale, (k[2]+0.7f)*gscale);
00621         glVertex3f((k[0]+0.3f)*gscale, (k[1]     )*gscale, (k[2]+0.7f)*gscale);
00622         glVertex3f((k[0]+0.7f)*gscale, (k[1]     )*gscale, (k[2]+0.3f)*gscale);
00623           }
00624         if (g->neighbors[3] == &emptyGrid)
00625           {
00626         glColor3f(0.5f,1.0f,0.5f);
00627         glVertex3f((k[0]+0.3f)*gscale, (k[1]+1   )*gscale, (k[2]+0.3f)*gscale);
00628         glVertex3f((k[0]+0.7f)*gscale, (k[1]+1   )*gscale, (k[2]+0.7f)*gscale);
00629         glVertex3f((k[0]+0.3f)*gscale, (k[1]+1   )*gscale, (k[2]+0.7f)*gscale);
00630         glVertex3f((k[0]+0.7f)*gscale, (k[1]+1   )*gscale, (k[2]+0.3f)*gscale);
00631           }
00632         if (g->neighbors[4] == &emptyGrid)
00633           {
00634         glColor3f(0.0f,0.0f,1.0f);
00635         glVertex3f((k[0]+0.3f)*gscale, (k[1]+0.3f)*gscale, (k[2]     )*gscale);
00636         glVertex3f((k[0]+0.7f)*gscale, (k[1]+0.7f)*gscale, (k[2]     )*gscale);
00637         glVertex3f((k[0]+0.7f)*gscale, (k[1]+0.3f)*gscale, (k[2]     )*gscale);
00638         glVertex3f((k[0]+0.3f)*gscale, (k[1]+0.7f)*gscale, (k[2]     )*gscale);
00639           }
00640         if (g->neighbors[5] == &emptyGrid)
00641           {
00642         glColor3f(0.5f,0.5f,1.0f);
00643         glVertex3f((k[0]+0.3f)*gscale, (k[1]+0.3f)*gscale, (k[2]+1   )*gscale);
00644         glVertex3f((k[0]+0.7f)*gscale, (k[1]+0.7f)*gscale, (k[2]+1   )*gscale);
00645         glVertex3f((k[0]+0.7f)*gscale, (k[1]+0.3f)*gscale, (k[2]+1   )*gscale);
00646         glVertex3f((k[0]+0.3f)*gscale, (k[1]+0.7f)*gscale, (k[2]+1   )*gscale);
00647           }
00648         if (!g->empty)
00649           {
00650         glColor3f(0.5f,0.5f,0.5f);
00651         int x,y,z;
00652         for (z = 0; z<=GRIDDIM; z++)
00653           for (y = 0; y<=GRIDDIM; y++)
00654             {
00655               if ((y==0 || y==GRIDDIM) && (z==0 || z==GRIDDIM)) continue;
00656               glVertex3f((k[0]*GRIDDIM          )*cscale, (k[1]*GRIDDIM + y    )*cscale, (k[2]*GRIDDIM + z    )*cscale);
00657               glVertex3f((k[0]*GRIDDIM + GRIDDIM)*cscale, (k[1]*GRIDDIM + y    )*cscale, (k[2]*GRIDDIM + z    )*cscale);
00658             }
00659         for (z = 0; z<=GRIDDIM; z++)
00660           for (x = 0; x<=GRIDDIM; x++)
00661             {
00662               if ((x==0 || x==GRIDDIM) && (z==0 || z==GRIDDIM)) continue;
00663               glVertex3f((k[0]*GRIDDIM + x    )*cscale, (k[1]*GRIDDIM          )*cscale, (k[2]*GRIDDIM + z    )*cscale);
00664               glVertex3f((k[0]*GRIDDIM + x    )*cscale, (k[1]*GRIDDIM + GRIDDIM)*cscale, (k[2]*GRIDDIM + z    )*cscale);
00665             }
00666         for (y = 0; y<=GRIDDIM; y++)
00667           for (x = 0; x<=GRIDDIM; x++)
00668             {
00669               if ((x==0 || x==GRIDDIM) && (y==0 || y==GRIDDIM)) continue;
00670               glVertex3f((k[0]*GRIDDIM + x    )*cscale, (k[1]*GRIDDIM + y    )*cscale, (k[2]*GRIDDIM          )*cscale);
00671               glVertex3f((k[0]*GRIDDIM + x    )*cscale, (k[1]*GRIDDIM + y    )*cscale, (k[2]*GRIDDIM + GRIDDIM)*cscale);
00672             }
00673           }
00674       }
00675     glEnd();
00676       }
00677 
00678 template<class DataTypes>
00679 SpatialGridContainer<DataTypes>::SpatialGridContainer()
00680 : grid(NULL)
00681 , d_cellWidth(initData(&d_cellWidth, (Real)1.0, "cellWidth", "Width each cell in the grid. If it is used to compute neighboors, it should be greater that the max radius considered."))
00682 , d_showGrid(initData(&d_showGrid, false, "showGrid", "activate rendering of the grid"))
00683 , d_autoUpdate(initData(&d_autoUpdate, false, "autoUpdate", "Automatically update the grid at each iteration."))
00684 , d_sortPoints(initData(&d_sortPoints, false, "sortPoints", "Sort points depending on which cell they are in the grid. This is required for efficient collision detection."))
00685 , mstate(NULL)
00686 {
00687     this->f_listening.setValue(true);
00688 }
00689 
00690 template<class DataTypes>
00691 SpatialGridContainer<DataTypes>::~SpatialGridContainer()
00692 {
00693     if (grid != NULL)
00694     delete grid;
00695 }
00696 
00697 template<class DataTypes>
00698 void SpatialGridContainer<DataTypes>::init()
00699 {
00700     mstate = dynamic_cast<core::componentmodel::behavior::MechanicalState<DataTypes>*>(this->getContext()->getMechanicalState());
00701     grid = new Grid(d_cellWidth.getValue());
00702 }
00703 
00704 template<class DataTypes>
00705 void SpatialGridContainer<DataTypes>::reinit()
00706 {
00707     if (grid == NULL || grid->getCellWidth() != d_cellWidth.getValue())
00708     {
00709     if (grid != NULL)
00710         delete grid;
00711     grid = new Grid(d_cellWidth.getValue());
00712     }
00713 }
00714 
00715 template<class DataTypes>
00716 bool SpatialGridContainer<DataTypes>::sortPoints()
00717 {
00718     if (mstate)
00719     updateGrid(*mstate->getX());
00720     if (this->f_printLog.getValue())
00721     std::cout << "SpatialGridContainer::sortPoints(): sorting..."<<std::endl;
00722     helper::vector<unsigned int> old2new, new2old;
00723     grid->reorderIndices(&old2new, &new2old);
00724     // check if the mapping actually changed something
00725     bool identity = true;
00726     for (unsigned int i=0;i<old2new.size();++i)
00727     if (old2new[i] != i)
00728     {
00729         identity = false;
00730         break;
00731     }
00732     if (identity)
00733     {
00734     if(this->f_printLog.getValue())
00735         std::cout << "SpatialGridContainer::sortPoints(): no changes."<<std::endl;
00736     return false;
00737     }
00738     if(this->f_printLog.getValue())
00739     {
00740         std::cout << "map:";
00741         for (unsigned int i=0;i<new2old.size();++i)
00742             std::cout << " "<<new2old[i]<<"->"<<i;
00743         std::cout << std::endl;
00744         std::cout << "invmap:";
00745         for (unsigned int i=0;i<old2new.size();++i)
00746             std::cout << " "<<i<<"->"<<old2new[i];
00747         std::cout << std::endl;
00748     }
00749 
00750     sofa::component::topology::PointSetTopologyModifier* pointMod; 
00751     this->getContext()->get(pointMod);
00752 
00753     if (pointMod)
00754     {
00755     if(this->f_printLog.getValue())
00756         std::cout << "SpatialGridContainer::sortPoints(): renumber using PointSetTopologyModifier."<<std::endl;
00757 
00758         pointMod->renumberPoints(new2old,old2new);
00759     }
00760     else
00761     {
00762     MechanicalObject<DataTypes>* object = dynamic_cast<MechanicalObject<DataTypes>*>(this->mstate);
00763     if (object != NULL)
00764     {
00765         if(this->f_printLog.getValue())
00766         std::cout << "SpatialGridContainer::sortPoints(): renumber using MechanicalObject."<<std::endl;
00767         object->renumberValues(new2old);
00768     }
00769     else
00770     {
00771         std::cout << "SpatialGridContainer::sortPoints(): no external object supporting renumbering!"<<std::endl;
00772     }
00773     }
00774     return true;
00775 }
00776 template<class DataTypes>
00777 void SpatialGridContainer<DataTypes>::handleEvent(sofa::core::objectmodel::Event* event)
00778 {
00779     if (/* simulation::AnimateBeginEvent* ev = */ dynamic_cast<simulation::AnimateBeginEvent*>(event))
00780     //if (simulation::AnimateEndEvent* ev = dynamic_cast<simulation::AnimateEndEvent*>(event))
00781     {
00782     if (d_sortPoints.getValue())
00783     {
00784         sortPoints();
00785     }
00786     else if (d_autoUpdate.getValue())
00787     {
00788         if (mstate)
00789         updateGrid(*mstate->getX());
00790     }
00791     }
00792 }
00793 
00794 template<class DataTypes>
00795 void SpatialGridContainer<DataTypes>::draw()
00796 {
00797     if (!d_showGrid.getValue())
00798     return;
00799     if (grid != NULL)
00800     grid->draw();
00801 }
00802 
00803 } // namespace container
00804 
00805 } // namespace component
00806 
00807 } // namespace sofa
00808 
00809 #endif

Generated on Sun Nov 23 02:49:36 2008 for Sofa by  doxygen 1.5.7.1