octree.cpp
Go to the documentation of this file.
00001 /******************************************************************************
00002  * \file
00003  *
00004  * $Id:$
00005  *
00006  * Copyright (C) Brno University of Technology (BUT)
00007  *
00008  * This file is part of software developed by dcgm-robotics@FIT group.
00009  *
00010  * Author: Jan Gorig (xgorig01@stud.fit.vutbr.cz)
00011  * Supervised by: Michal Spanel (spanel@fit.vutbr.cz)
00012  * Date: 12/04/2012
00013  *
00014  * This file is free software: you can redistribute it and/or modify
00015  * it under the terms of the GNU Lesser General Public License as published by
00016  * the Free Software Foundation, either version 3 of the License, or
00017  * (at your option) any later version.
00018  *
00019  * This file is distributed in the hope that it will be useful,
00020  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00022  * GNU Lesser General Public License for more details.
00023  *
00024  * You should have received a copy of the GNU Lesser General Public License
00025  * along with this file.  If not, see <http://www.gnu.org/licenses/>.
00026  */
00027 
00028 #include <cstdio>
00029 #include <srs_env_model/but_server/objtree/octree.h>
00030 #include <srs_env_model/but_server/objtree/filter.h>
00031 #include <srs_env_model/but_server/objtree/node.h>
00032 
00033 namespace objtree
00034 {
00035 
00041 Octree::Octree(unsigned int maxDepth) :
00042     m_rootSize(0.0f, 0.0f, 0.0f, 16.0f, 16.0f, 16.0f)
00043 {
00044     m_root = new Node;
00045     m_maxId = 0;
00046     m_maxDepth = maxDepth;
00047 }
00048 
00055 Octree::Octree(const Box &rootSize, unsigned int maxDepth) :
00056     m_rootSize(rootSize)
00057 {
00058     m_root = new Node;
00059     m_maxId = 0;
00060     m_maxDepth = maxDepth;
00061 }
00062 
00066 Octree::~Octree()
00067 {
00068     delete m_root;
00069 }
00070 
00074 void Octree::clear()
00075 {
00076     delete m_root;
00077     m_objects.clear();
00078 
00079     m_root = new Node;
00080     m_maxId = 0;
00081 }
00082 
00088 unsigned int Octree::insertOnFit(Object* object)
00089 {
00090     Node *node = m_root;
00091 
00092     Box box(m_rootSize);
00093     Box childBox;
00094 
00095     bool fits = true;
00096     unsigned char i;
00097 
00098     while(fits)
00099     {
00100         for(i = 0; !(fits = object->fitsIntoBox(Node::getChildBox(i, childBox, box))) && i < Node::CHILDREN; i++);
00101 
00102         if(fits)
00103         {
00104             node = node->child(i, true);
00105             box = childBox;
00106         }
00107     }
00108 
00109     node->add(object);
00110     m_objects[m_maxId] = object;
00111     object->setId(m_maxId++);
00112 
00113     return object->id();
00114 }
00115 
00124 unsigned int Octree::insertOnInterfere(Object* object, Node *node, Box box, unsigned int depth)
00125 {
00126     Box childBox;
00127 
00128     for(unsigned char i = 0; i < Node::CHILDREN; i++)
00129     {
00130         if(object->interfereWithBox(Node::getChildBox(i, childBox, box)))
00131         {
00132             Node *child = node->child(i, true);
00133 
00134             if(depth < m_maxDepth)
00135             {
00136                 insertOnInterfere(object, child, childBox, depth+1);
00137             }
00138             else
00139             {
00140                 child->add(object);
00141             }
00142         }
00143     }
00144 
00145     return object->id();
00146 }
00147 
00158 unsigned int Octree::insertUpdateOnInterfere(Object* object, Node *node, Box box, bool &inserted, unsigned int depth)
00159 {
00160     Box childBox;
00161 
00162     for(unsigned char i = 0; i < Node::CHILDREN; i++)
00163     {
00164         if(object->interfereWithBox(Node::getChildBox(i, childBox, box)))
00165         {
00166             Node *child = node->child(i, true);
00167 
00168             if(depth < m_maxDepth)
00169             {
00170                 insertUpdateOnInterfere(object, child, childBox, inserted, depth+1);
00171             }
00172             else
00173             {
00174                 //Find similar object
00175                 Object *similar = NULL;
00176 
00177                 for(std::list<Object*>::const_iterator j = child->objects().begin(); j != child->objects().end() && !similar; j++)
00178                 {
00179                     if(*j != object && (*j)->isSimilar(object))
00180                     {
00181                         similar = *j;
00182                     }
00183                 }
00184 
00185                 for(unsigned int n = 0; n < Node::NEIGHBORS && !similar; n++)
00186                 {
00187                     Node *neighbor = child->neighbor(n);
00188                     if(neighbor == NULL)
00189                     {
00190                         continue;
00191                     }
00192 
00193                     for(std::list<Object*>::const_iterator j = neighbor->objects().begin(); j != neighbor->objects().end() && !similar; j++)
00194                     {
00195                         if(*j != object && (*j)->isSimilar(object))
00196                         {
00197                             similar = *j;
00198                         }
00199                     }
00200                 }
00201 
00202                 child->add(object);
00203 
00204                 //We have found a similar object
00205                 if(similar != NULL)
00206                 {
00207                     //Replace similar object in objects list
00208                     if(!inserted)
00209                     {
00210                         m_objects[similar->id()] = object;
00211                         object->setId(similar->id());
00212                         inserted = true;
00213 #if HISTORY_ENABLED
00214                         object->takeHistory(similar);
00215 #endif
00216                     }
00217                     //We have already replaced other object
00218                     else
00219                     {
00220                         m_objects.erase(similar->id());
00221                     }
00222 
00223                     delete similar;
00224                 }
00225                 //Similar object hasn't been found
00226                 else
00227                 {
00228                     if(!inserted)
00229                     {
00230                         if(!object->hasId())
00231                         {
00232                             m_objects[m_maxId] = object;
00233                             object->setId(m_maxId++);
00234                         }
00235                         else
00236                         {
00237                             m_objects[object->id()] = object;
00238                         }
00239                     }
00240                 }
00241             }
00242         }
00243     }
00244 
00245     return object->id();
00246 }
00247 
00256 Object* Octree::getSimilarObject(const Object *object, Node *node, Box box, unsigned int depth)
00257 {
00258     Box childBox;
00259     Object *similar;
00260 
00261     for(unsigned char i = 0; i < Node::CHILDREN; i++)
00262     {
00263         Node *child = node->child(i);
00264 
00265         if(!child) continue;
00266 
00267         if(object->interfereWithBox(Node::getChildBox(i, childBox, box)))
00268         {
00269             if(depth < m_maxDepth)
00270             {
00271                 similar = getSimilarObject(object, child, childBox, depth+1);
00272                 if(similar) return similar;
00273             }
00274             else
00275             {
00276                 for(std::list<Object*>::const_iterator j = node->objects().begin(); j != node->objects().end(); j++)
00277                 {
00278                     if(*j != object && (*j)->isSimilar(object))
00279                     {
00280                         return *j;
00281                     }
00282                 }
00283 
00284                 for(unsigned int n = 0; n < Node::NEIGHBORS; n++)
00285                 {
00286                     Node *neighbor = child->neighbor(n);
00287 
00288                     if(!neighbor) continue;
00289 
00290                     for(std::list<Object*>::const_iterator j = neighbor->objects().begin(); j != neighbor->objects().end(); j++)
00291                     {
00292                         if(*j != object && (*j)->isSimilar(object))
00293                         {
00294                             return *j;
00295                         }
00296                     }
00297                 }
00298             }
00299         }
00300     }
00301 
00302     return NULL;
00303 }
00304 
00310 Object* Octree::getSimilarObject(const Object* object)
00311 {
00312     return getSimilarObject(object, m_root, m_rootSize);
00313 }
00314 
00320 unsigned int Octree::insert(Object* object)
00321 {
00322     if(!object->hasId())
00323     {
00324         m_objects[m_maxId] = object;
00325         object->setId(m_maxId++);
00326     }
00327     else
00328     {
00329         m_objects[object->id()] = object;
00330     }
00331 
00332     return insertOnInterfere(object, m_root, m_rootSize);
00333 }
00334 
00341 unsigned int Octree::insertUpdate(Object* object)
00342 {
00343     bool inserted = false;
00344     return insertUpdateOnInterfere(object, m_root, m_rootSize, inserted);
00345 }
00346 
00354 unsigned int Octree::insertUpdate2(Object* object)
00355 {
00356     Object *similar = getSimilarObject(object, m_root, m_rootSize);
00357 
00358     if(similar)
00359     {
00360         m_objects[similar->id()] = object;
00361         object->setId(similar->id());
00362 
00363         delete similar;
00364     }
00365     else
00366     {
00367         m_objects[m_maxId] = object;
00368         object->setId(m_maxId++);
00369     }
00370 
00371     return insertOnInterfere(object, m_root, m_rootSize);
00372 }
00373 
00381 bool Octree::isPositionFree(float x, float y, float z)
00382 {
00383     Node *node = m_root;
00384 
00385     Box box(m_rootSize);
00386 
00387     for(;;)
00388     {
00389         unsigned char id = 0;
00390 
00391         if(x >= box.x+box.w/2.0f) id += 1;
00392         if(y >= box.y+box.h/2.0f) id += 2;
00393         if(z >= box.z+box.d/2.0f) id += 4;
00394 
00395         node = node->child(id);
00396 
00397         if(node == NULL)
00398         {
00399             return true;
00400         }
00401 
00402         for(std::list<Object*>::const_iterator i = node->objects().begin(); i != node->objects().end(); i++)
00403         {
00404             if((*i)->isPointInside(x, y, z))
00405             {
00406                 return false;
00407             }
00408         }
00409 
00410         Node::getChildBox(id, box, box);
00411     }
00412 }
00413 
00420 void Octree::nodes(std::list<Box> &nodesList, std::set<Object*> &objectList, const Filter *filter)
00421 {
00422     nodes(nodesList, objectList, filter, m_rootSize, m_root);
00423 }
00424 
00433 void Octree::nodes(std::list<Box> &nodesList, std::set<Object*> &objectList, const Filter *filter, Box dim, Node *node)
00434 {
00435     if(!filter->filter(dim)) return;
00436 
00437     for(std::list<Object*>::const_iterator i = node->objects().begin(); i != node->objects().end(); i++)
00438     {
00439         objectList.insert(*i);
00440     }
00441 
00442     nodesList.push_back(dim);
00443 
00444     for(unsigned int i = 0; i < Node::CHILDREN; i++)
00445     {
00446         Node *child = node->child(i);
00447 
00448         if(child)
00449         {
00450             Box newDim;
00451             Node::getChildBox(i, newDim, dim);
00452             nodes(nodesList, objectList, filter, newDim, child);
00453         }
00454     }
00455 }
00456 
00462 void Octree::objects(std::set<Object*> &objectList, const Filter *filter)
00463 {
00464     std::list<Box> nodesList;
00465     nodes(nodesList, objectList, filter, m_rootSize, m_root);
00466 }
00467 
00468 const Object* Octree::object(unsigned int id) const
00469 {
00470     std::map<unsigned int, Object*>::const_iterator i = m_objects.find(id);
00471 
00472     if(i != m_objects.end()) return i->second;
00473     else return NULL;
00474 }
00475 
00481 bool Octree::removeObject(unsigned int id)
00482 {
00483     std::map<unsigned int, Object*>::iterator i = m_objects.find(id);
00484 
00485     if(i != m_objects.end())
00486     {
00487         delete i->second;
00488         m_objects.erase(i);
00489 
00490         return true;
00491     }
00492     else
00493     {
00494         return false;
00495     }
00496 }
00497 
00502 Node* Octree::root() const
00503 {
00504     return m_root;
00505 }
00506 
00511 unsigned int Octree::maxId() const
00512 {
00513     return m_maxId;
00514 }
00515 
00520 unsigned int Octree::count() const
00521 {
00522     return m_objects.size();
00523 }
00524 
00529 const std::map<unsigned int, Object*>& Octree::objectsAll() const
00530 {
00531     return m_objects;
00532 }
00533 
00534 }


srs_env_model
Author(s): Vit Stancl (stancl@fit.vutbr.cz), Tomas Lokaj, Jan Gorig, Michal Spanel (spanel@fit.vutbr.cz)
autogenerated on Mon Oct 6 2014 08:05:05