$search
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 }