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/node.h> 00030 00031 namespace objtree 00032 { 00033 00040 Node::Node(unsigned char place, Node *parent) 00041 { 00042 m_place = place; 00043 m_parent = parent; 00044 00045 if(m_parent != NULL) 00046 { 00047 //Update neighbor pointers in neighbors 00048 for(unsigned char neighbor = 0; neighbor < NEIGHBORS; neighbor++) 00049 { 00050 m_neighbors[neighbor] = computeNeighbor(neighbor); 00051 00052 if(m_neighbors[neighbor] != NULL) 00053 { 00054 m_neighbors[neighbor]->m_neighbors[reverseNeighborId(neighbor)] = this; 00055 } 00056 } 00057 } 00058 else 00059 { 00060 //Root node hasn't got any neighbors 00061 for(unsigned char neighbor = 0; neighbor < NEIGHBORS; neighbor++) 00062 { 00063 m_neighbors[neighbor] = NULL; 00064 } 00065 } 00066 00067 for(unsigned char i = 0; i < CHILDREN; i++) 00068 { 00069 m_children[i] = NULL; 00070 } 00071 } 00072 00076 Node::~Node() 00077 { 00078 //Nullify all neighbor pointers to this node 00079 for(unsigned char neighbor = 0; neighbor < NEIGHBORS; neighbor++) 00080 { 00081 if(m_neighbors[neighbor] != NULL) 00082 { 00083 m_neighbors[neighbor]->m_neighbors[reverseNeighborId(neighbor)] = NULL; 00084 } 00085 } 00086 00087 //Delete all children 00088 for(unsigned char place = 0; place < CHILDREN; place++) 00089 { 00090 if(m_children[place]) delete m_children[place]; 00091 } 00092 00093 //Delete all objects 00094 for(std::list<Object*>::iterator i = m_objects.begin(); i != m_objects.end(); i++) 00095 { 00096 (*i)->removeNode(this); 00097 delete *i; 00098 } 00099 } 00100 00105 Node* Node::parent() 00106 { 00107 return m_parent; 00108 } 00109 00116 Node* Node::child(unsigned char place, bool createNew) 00117 { 00118 if(!m_children[place] && createNew) 00119 { 00120 m_children[place] = new Node(place, this); 00121 } 00122 00123 return m_children[place]; 00124 } 00125 00131 Node* Node::neighbor(unsigned char dir) 00132 { 00133 return m_neighbors[dir]; 00134 } 00135 00140 const std::list<Object*>& Node::objects() const 00141 { 00142 return m_objects; 00143 } 00144 00149 void Node::add(Object* object) 00150 { 00151 m_objects.push_back(object); 00152 object->newNode(this); 00153 } 00154 00162 Box& Node::getChildBox(unsigned char place, Box &childBox, const Box &parentBox) 00163 { 00164 childBox = parentBox; 00165 00166 childBox.w/=2.0f; 00167 childBox.h/=2.0f; 00168 childBox.d/=2.0f; 00169 00170 switch(place) 00171 { 00172 case 0: 00173 break; 00174 case 1: 00175 childBox.x+=childBox.w; 00176 break; 00177 case 2: 00178 childBox.y+=childBox.h; 00179 break; 00180 case 3: 00181 childBox.x+=childBox.w; 00182 childBox.y+=childBox.h; 00183 break; 00184 case 4: 00185 childBox.z+=childBox.d; 00186 break; 00187 case 5: 00188 childBox.x+=childBox.w; 00189 childBox.z+=childBox.d; 00190 break; 00191 case 6: 00192 childBox.y+=childBox.h; 00193 childBox.z+=childBox.d; 00194 break; 00195 case 7: 00196 childBox.x+=childBox.w; 00197 childBox.y+=childBox.h; 00198 childBox.z+=childBox.d; 00199 break; 00200 } 00201 00202 return childBox; 00203 } 00204 00211 Node* Node::parentNeighborChild(unsigned char parentNeighbor, unsigned char child) 00212 { 00213 if(m_parent->m_neighbors[parentNeighbor] != NULL) 00214 { 00215 return m_parent->m_neighbors[parentNeighbor]->m_children[child]; 00216 } 00217 00218 return NULL; 00219 } 00220 00221 /* 00222 * Neighbors ids (from top view) 00223 * Top part: Middle part: Bottom part: 00224 * 6 7 8 14 15 16 23 24 25 00225 * 3 4 5 12 13 20 21 22 00226 * 0 1 2 9 10 11 17 18 19 00227 * 00228 * Node children ids (from top view) 00229 * Top part: Bottom part: 00230 * 2 3 6 7 00231 * 0 1 4 5 00232 * 00233 * Temporary ids (from top view) 00234 * 12 13 14 15 28 29 30 31 44 45 46 47 60 61 62 63 00235 * 8 9 10 11 24 25 26 27 40 41 42 43 56 57 58 59 00236 * 4 5 6 7 20 21 22 23 36 37 38 39 52 53 54 55 00237 * 0 1 2 3 16 17 18 19 32 33 34 35 48 49 50 51 00238 */ 00239 00246 Node* Node::computeNeighbor(unsigned char dir) 00247 { 00248 if(dir >= 13) dir++; 00249 00250 unsigned char x = m_place%2+1; 00251 unsigned char y = (m_place%4)/2+1; 00252 unsigned char z = m_place/4+1; 00253 00254 x -= dir%3 == 0; 00255 x += (dir+1)%3 == 0; 00256 00257 y -= dir%9 <= 2; 00258 y += dir%9 >= 6; 00259 00260 z -= dir <= 8; 00261 z += dir >= 18; 00262 00263 unsigned char child = 1-x%2; 00264 if(y%2 == 0) child += 2; 00265 if(z%2 == 0) child += 4; 00266 00267 x -= x >= 2; 00268 y -= y >= 2; 00269 z -= z >= 2; 00270 00271 unsigned char parent = z*9+y*3+x; 00272 00273 if(parent == 13) return m_parent->m_children[child]; 00274 if(parent > 13) parent--; 00275 00276 return parentNeighborChild(parent, child); 00277 } 00278 00284 unsigned char Node::reverseNeighborId(unsigned char dir) 00285 { 00286 return 25-dir; 00287 } 00288 00294 void Node::removeObject(Object *object) 00295 { 00296 m_objects.remove(object); 00297 00298 if(m_objects.size() == 0) 00299 { 00300 m_parent->m_children[m_place] = NULL; 00301 m_parent->deleteIfEmpty(); 00302 delete this; 00303 } 00304 } 00305 00309 void Node::deleteIfEmpty() 00310 { 00311 //We don't want to delete root node 00312 if(m_parent == NULL) 00313 { 00314 return; 00315 } 00316 00317 for(unsigned char child = 0; child < CHILDREN; child++) 00318 { 00319 if(m_children[child] != NULL) 00320 { 00321 return; 00322 } 00323 } 00324 00325 if(m_objects.size() != 0) 00326 { 00327 return; 00328 } 00329 00330 m_parent->m_children[m_place] = NULL; 00331 m_parent->deleteIfEmpty(); 00332 delete this; 00333 } 00334 00335 }