octomap 1.5.0
include/octomap/OcTreeDataNode.hxx
Go to the documentation of this file.
00001 // $Id: OcTreeDataNode.hxx 397 2012-08-02 13:34:36Z ahornung $
00002 
00011 /*
00012  * Copyright (c) 2009, K. M. Wurm, A. Hornung, University of Freiburg
00013  * All rights reserved.
00014  *
00015  * Redistribution and use in source and binary forms, with or without
00016  * modification, are permitted provided that the following conditions are met:
00017  *
00018  *     * Redistributions of source code must retain the above copyright
00019  *       notice, this list of conditions and the following disclaimer.
00020  *     * Redistributions in binary form must reproduce the above copyright
00021  *       notice, this list of conditions and the following disclaimer in the
00022  *       documentation and/or other materials provided with the distribution.
00023  *     * Neither the name of the University of Freiburg nor the names of its
00024  *       contributors may be used to endorse or promote products derived from
00025  *       this software without specific prior written permission.
00026  *
00027  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00028  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00029  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00030  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00031  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00032  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00033  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00034  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00035  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00036  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00037  * POSSIBILITY OF SUCH DAMAGE.
00038  */
00039 
00040 namespace octomap {
00041 
00042   template <typename T>
00043   OcTreeDataNode<T>::OcTreeDataNode()
00044    : children(NULL)
00045   {
00046 
00047   }
00048 
00049   template <typename T>
00050   OcTreeDataNode<T>::OcTreeDataNode(T initVal)
00051    : children(NULL), value(initVal)
00052   {
00053 
00054   }
00055 
00056   template <typename T>
00057   OcTreeDataNode<T>::OcTreeDataNode(const OcTreeDataNode<T>& rhs)
00058    : children(NULL), value(rhs.value)
00059   {
00060     if (rhs.hasChildren()){
00061       allocChildren();
00062       for (unsigned i = 0; i<8; ++i){
00063         if (rhs.children[i])
00064           children[i] = new OcTreeDataNode<T>(*(rhs.children[i]));
00065 
00066       }
00067     }
00068   }
00069 
00070 
00071 
00072   template <typename T>
00073   OcTreeDataNode<T>::~OcTreeDataNode()
00074   {
00075     if (children != NULL) {
00076       for (unsigned int i=0; i<8; i++) {
00077         if (children[i] != NULL) delete children[i];
00078       }
00079       delete[] children;
00080     }
00081 
00082   }
00083 
00084   template <typename T>
00085   bool OcTreeDataNode<T>::operator== (const OcTreeDataNode<T>& rhs) const{
00086     return rhs.value == value;
00087   }
00088 
00089   // ============================================================
00090   // =  children          =======================================
00091   // ============================================================
00092 
00093   template <typename T>
00094   bool OcTreeDataNode<T>::createChild(unsigned int i) {
00095     if (children == NULL) {
00096       allocChildren();
00097     }
00098     assert (children[i] == NULL);
00099     children[i] = new OcTreeDataNode<T>();
00100     return true;
00101   }
00102 
00103   template <typename T>
00104   bool OcTreeDataNode<T>::childExists(unsigned int i) const {
00105     assert(i < 8);
00106     if ((children != NULL) && (children[i] != NULL))
00107       return true;
00108     else
00109       return false;
00110   }
00111 
00112   template <typename T>
00113   void OcTreeDataNode<T>::deleteChild(unsigned int i) {
00114     assert((i < 8) && (children != NULL));
00115     assert(children[i] != NULL);
00116     delete children[i];
00117     children[i] = NULL;
00118   }
00119 
00120   template <typename T>
00121   OcTreeDataNode<T>* OcTreeDataNode<T>::getChild(unsigned int i) {
00122     assert((i < 8) && (children != NULL));
00123     assert(children[i] != NULL);
00124     return children[i];
00125   }
00126 
00127   template <typename T>
00128   const OcTreeDataNode<T>* OcTreeDataNode<T>::getChild(unsigned int i) const {
00129     assert((i < 8) && (children != NULL));
00130     assert(children[i] != NULL);
00131     return children[i];
00132   }
00133 
00134   template <typename T>
00135   bool OcTreeDataNode<T>::hasChildren() const {
00136     if (children == NULL) return false;
00137     for (unsigned int i = 0; i<8; i++)
00138       if (childExists(i)) return true;
00139     return false;
00140   }
00141 
00142   // ============================================================
00143   // =  pruning           =======================================
00144   // ============================================================
00145 
00146 
00147   template <typename T>
00148   bool OcTreeDataNode<T>::collapsible() const {
00149     // all children must exist, must not have children of
00150     // their own and have the same occupancy probability
00151     if (!childExists(0) || getChild(0)->hasChildren())
00152       return false;
00153 
00154     T childValue = getChild(0)->getValue();
00155 
00156     for (unsigned int i = 1; i<8; i++) {
00157       if (!childExists(i)) return false;
00158       else if (getChild(i)->hasChildren()) return false;
00159       else if (! (getChild(i)->getValue() == childValue)) return false;
00160     }
00161     return true;
00162   }
00163 
00164   template <typename T>
00165   bool OcTreeDataNode<T>::pruneNode() {
00166 
00167     if (!this->collapsible())
00168       return false;
00169 
00170     // set value to children's values (all assumed equal)
00171     setValue(getChild(0)->getValue());
00172 
00173     // delete children
00174     for (unsigned int i=0;i<8;i++) {
00175       delete children[i];
00176     }
00177     delete[] children;
00178     children = NULL;
00179 
00180     return true;
00181   }
00182 
00183   template <typename T>
00184   void OcTreeDataNode<T>::expandNode() {
00185     assert(!hasChildren());
00186 
00187     for (unsigned int k=0; k<8; k++) {
00188       createChild(k);
00189       children[k]->setValue(value);
00190     }
00191   }
00192 
00193   // ============================================================
00194   // =  File IO           =======================================
00195   // ============================================================
00196 
00197   template <typename T>
00198   std::istream& OcTreeDataNode<T>::readValue(std::istream &s) {
00199 
00200     char children_char;
00201 
00202     // read data:
00203     s.read((char*) &value, sizeof(value));
00204     s.read((char*)&children_char, sizeof(char));
00205     std::bitset<8> children ((unsigned long long) children_char);
00206 
00207     // std::cout << "read: " << value << " "
00208     //           << children.to_string<char,std::char_traits<char>,std::allocator<char> >()
00209     //           << std::endl;
00210 
00211     for (unsigned int i=0; i<8; i++) {
00212       if (children[i] == 1){
00213         createChild(i);
00214         getChild(i)->readValue(s);
00215       }
00216     }
00217     return s;
00218   }
00219 
00220 
00221   template <typename T>
00222   std::ostream& OcTreeDataNode<T>::writeValue(std::ostream &s) const{
00223 
00224     // 1 bit for each children; 0: empty, 1: allocated
00225     std::bitset<8> children;
00226 
00227     for (unsigned int i=0; i<8; i++) {
00228       if (childExists(i))
00229         children[i] = 1;
00230       else
00231         children[i] = 0;
00232     }
00233 
00234     char children_char = (char) children.to_ulong();
00235     s.write((const char*) &value, sizeof(value));
00236     s.write((char*)&children_char, sizeof(char));
00237 
00238     // std::cout << "wrote: " << value << " "
00239     //           << children.to_string<char,std::char_traits<char>,std::allocator<char> >() 
00240     //           << std::endl;
00241 
00242     // write children's children
00243     for (unsigned int i=0; i<8; i++) {
00244       if (children[i] == 1) {
00245         this->getChild(i)->writeValue(s);
00246       }
00247     }
00248     return s;
00249   }
00250 
00251 
00252   // ============================================================
00253   // =  private methodes  =======================================
00254   // ============================================================
00255   template <typename T>
00256   void OcTreeDataNode<T>::allocChildren() {
00257     children = new OcTreeDataNode<T>*[8];
00258     for (unsigned int i=0; i<8; i++) {
00259       children[i] = NULL;
00260     }
00261   }
00262 
00263 
00264 } // end namespace
00265