SpatialGridPointModel.cpp

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 #include <sofa/component/collision/SpatialGridPointModel.h>
00026 #include <sofa/component/collision/CubeModel.h>
00027 #include <sofa/core/ObjectFactory.h>
00028 #include <vector>
00029 #include <sofa/helper/system/gl.h>
00030 
00031 namespace sofa
00032 {
00033 
00034 namespace component
00035 {
00036 
00037 namespace collision
00038 {
00039 
00040 SOFA_DECL_CLASS(SpatialGridPointModel)
00041 
00042 int SpatialGridPointModelClass = core::RegisterObject("Collision model which represents a set of points, spatially grouped using a SpatialGridContainer")
00043 .add< SpatialGridPointModel >()
00044 ;
00045 
00046 SpatialGridPointModel::SpatialGridPointModel()
00047 : d_leafScale(initData(&d_leafScale,0,"leafScale","at which level should the first cube layer be constructed.\nNote that this must not be greater than GRIDDIM_LOG2"))
00048 , grid(NULL)
00049 {
00050 }
00051 
00052 void SpatialGridPointModel::init()
00053 {
00054     this->PointModel::init();
00055     this->getContext()->get(grid);
00056 
00057     if (grid==NULL)
00058     {
00059     std::cerr << "ERROR: SpatialGridPointModel requires a Vec3 SpatialGridContainer.\n";
00060     return;
00061     }
00062 }
00063 
00064 bool SpatialGridPointModel::OctreeSorter::operator()(const Grid::Key& k1, const Grid::Key& k2)
00065 {
00066     for (int scale = root_shift; scale >= 0; --scale)
00067     {
00068     for (int c=k1.size()-1;c>=0;--c)
00069     {
00070         if ((k1[c]>>scale) < (k2[c]>>scale))
00071         return true;
00072         if ((k1[c]>>scale) > (k2[c]>>scale))
00073         return false;
00074     }
00075     }
00076     // they are equal
00077     return false;
00078 }
00079 
00080 void SpatialGridPointModel::computeBoundingTree(int maxDepth)
00081 {
00082     if (!grid)
00083     {
00084     this->PointModel::computeBoundingTree(maxDepth);
00085     return;
00086     }
00087     const bool verbose = this->f_printLog.getValue();
00088     int lscale = d_leafScale.getValue();
00089     if (lscale > Grid::GRIDDIM_LOG2) lscale = Grid::GRIDDIM_LOG2;
00090     int ldim = (1<<lscale);
00091     int nleaf = Grid::GRIDDIM/ldim;
00092     CubeModel* cubeModel = createPrevious<CubeModel>();
00093     const int npoints = mstate->getX()->size();
00094     bool updated = false;
00095     if (npoints != size)
00096     {
00097     resize(npoints);
00098     updated = true;
00099     }
00100     if (updated) cubeModel->resize(0);
00101     if (!isMoving() && !cubeModel->empty() && !updated) return; // No need to recompute BBox if immobile
00102 
00103     std::vector<OctreeCell> cells;
00104     Grid* g = grid->getGrid();
00105     Grid::const_iterator itgbegin = g->gridBegin();
00106     Grid::const_iterator itgend = g->gridEnd();
00107     //std::cout << "input: ";
00108     bool sorted = true;
00109     for (Grid::const_iterator itg = itgbegin; itg != itgend; ++itg)
00110     {
00111     Grid::Key k = itg->first;
00112     Grid::Grid* g = itg->second;
00113     if (g->empty) continue;
00114     for (int z0 = 0; z0<nleaf; z0++)
00115         for (int y0 = 0; y0<nleaf; y0++)
00116         for (int x0 = 0; x0<nleaf; x0++)
00117         {
00118             int pfirst = -1;
00119             int plast = -1;
00120             Grid::Key k2;
00121             k2[0] = k[0]*nleaf + x0;
00122             k2[1] = k[1]*nleaf + y0;
00123             k2[2] = k[2]*nleaf + z0;
00124             for (int z = 0; z<ldim; z++)
00125             for (int y = 0; y<ldim; y++)
00126                 for (int x = 0; x<ldim; x++)
00127                 {
00128                 Grid::Cell* c = g->cell+((z0*ldim+z)*Grid::DZ+(y0*ldim+y)*Grid::DY+(x0*ldim+x)*Grid::DX);
00129                 if (!c->plist.empty())
00130                 {
00131                     if (pfirst==-1)
00132                     pfirst = c->plist.front().index;
00133                     else if (c->plist.front().index != plast+1)
00134                     sorted = false;
00135                     plast = c->plist.back().index;
00136                     if (c->plist.back().index - c->plist.front().index +1 != (int)c->plist.size())
00137                     sorted = false;
00138                 }
00139                 }
00140             if (pfirst == -1) continue;
00141             cells.push_back(OctreeCell(k2, pfirst, plast));
00142             //std::cout << "  " << k2;
00143         }
00144     /*
00145     int pfirst = -1;
00146     int plast = -1;
00147     for (int i=0; i<Grid::NCELL; ++i)
00148     {
00149         Grid::Cell* c = g->cell+i;
00150         if (!c->plist.empty())
00151         {
00152         pfirst = c->plist.front().index;
00153         break;
00154         }
00155     }
00156     if (pfirst == -1) continue; // empty
00157     for (int i=Grid::NCELL-1; i>=0; --i)
00158     {
00159         Grid::Cell* c = g->cell+i;
00160         if (!c->plist.empty())
00161         {
00162         plast = c->plist.back().index;
00163         break;
00164         }
00165     }
00166     cells.push_back(OctreeCell(k, pfirst, plast));
00167     //std::cout << "  " << k;
00168     */
00169     }
00170     if (!sorted)
00171     {
00172     std::cerr << "ERROR(SpatialGridPointModel): points are not sorted in spatial grid."<<std::endl;
00173     }
00174     //std::cout << std::endl;
00175     cubeModel->resize(cells.size());
00176     if (cells.empty()) return;
00177     OctreeSorter s(maxDepth);
00178     Vector3::value_type cellSize = g->getCellWidth()*ldim; // *GRIDDIM;
00179     std::sort(cells.begin(), cells.end(), s);
00180     
00181     //std::cout << "sorted: ";
00182     for (unsigned int i=0;i<cells.size();i++)
00183     {
00184     Grid::Key k = cells[i].k;
00185     //std::cout << "  " << k;
00186     int pfirst = cells[i].pfirst;
00187     int plast = cells[i].plast;
00188     Vector3 minElem, maxElem;
00189     for (unsigned int c=0;c<k.size();++c)
00190     {
00191         minElem[c] = k[c]*cellSize;
00192         maxElem[c] = (k[c]+1)*cellSize;
00193     }
00194     cubeModel->setLeafCube(i, std::make_pair(Iterator(this,pfirst),Iterator(this,plast+1)), minElem, maxElem); // define the bounding box of the current cell
00195     }
00196     //std::cout << std::endl;
00197     //cubeModel->computeBoundingTree(maxDepth);
00198     int depth = 0;
00199     while (depth < maxDepth && cells.size() > 8)
00200     {
00201     if (verbose) std::cout << "SpatialGridPointModel: cube depth "<<depth<<": "<<cells.size()<<" cells ("<<(size*100/cells.size())*0.01<<" points/cell)."<<std::endl;
00202     // compact cells inplace
00203     int parent = -1;
00204     for (unsigned int i=0;i<cells.size();++i)
00205     {
00206         Grid::Key k = cells[i].k;
00207         //std::cout << "  " << k;
00208         for (unsigned int c=0;c<k.size();++c)
00209             k[c] >>= 1;
00210         if (parent == -1 || !(k == cells[parent].k))
00211         { // new parent
00212         //std::cout << "->"<<k;
00213         ++parent;
00214         cells[parent].k = k;
00215         cells[parent].pfirst = i;
00216         cells[parent].plast = i;
00217         }
00218         else
00219         { // continuing
00220         cells[parent].plast = i;
00221         }
00222     }
00223     //std::cout << std::endl;
00224     if (cells.size() > (unsigned int)parent+1)
00225     {
00226         cells.resize(parent+1);
00227         CubeModel* prevCubeModel = cubeModel;
00228         cubeModel = cubeModel->createPrevious<CubeModel>();
00229         cubeModel->resize(0);
00230         for (unsigned int i=0;i<cells.size();++i)
00231         {
00232         Grid::Key k = cells[i].k;
00233         int pfirst = cells[i].pfirst;
00234         int plast = cells[i].plast;
00235         Cube cfirst(prevCubeModel, pfirst);
00236         Cube clast(prevCubeModel, plast);
00237         cubeModel->addCube(Cube(prevCubeModel,pfirst),Cube(prevCubeModel,plast+1));
00238         }
00239     }
00240     ++depth;
00241     }
00242     CubeModel* root = cubeModel->createPrevious<CubeModel>();
00243     while (dynamic_cast<CubeModel*>(root->getPrevious()) != NULL)
00244     {
00245     root = dynamic_cast<CubeModel*>(root->getPrevious());
00246     }
00247     root->resize(0);
00248     root->addCube(Cube(cubeModel,0), Cube(cubeModel,cubeModel->getSize()));
00249 }
00250 
00251 } // namespace collision
00252 
00253 } // namespace component
00254 
00255 } // namespace sofa
00256 

Generated on Sun Nov 23 02:35:11 2008 for Sofa by  doxygen 1.5.7.1