OcTree.h
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2013, Fraunhofer FKIE
00003  *
00004  * Authors: Bastian Gaspers
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions are met:
00008  *
00009  * * Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * * Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * * Neither the name of the Fraunhofer FKIE nor the names of its
00015  *   contributors may be used to endorse or promote products derived from
00016  *   this software without specific prior written permission.
00017  *
00018  * This file is part of the StructureColoring ROS package.
00019  *
00020  * The StructureColoring ROS package is free software:
00021  * you can redistribute it and/or modify it under the terms of the
00022  * GNU Lesser General Public License as published by the Free
00023  * Software Foundation, either version 3 of the License, or
00024  * (at your option) any later version.
00025  *
00026  * The StructureColoring ROS package is distributed in the hope that it will be useful,
00027  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00028  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00029  * GNU Lesser General Public License for more details.
00030  *
00031  * You should have received a copy of the GNU Lesser General Public License
00032  * along with The StructureColoring ROS package.
00033  * If not, see <http://www.gnu.org/licenses/>.
00034  */
00035 
00036 #ifndef OCTREE_H_
00037 #define OCTREE_H_
00038 
00039 #include <boost/shared_ptr.hpp>
00040 #include <octreelib/spatialaggregate/octree.h>
00041 #include <octreelib/algorithm/downsample.h>
00042 #include "NormalEstimationValueClass.h"
00043 #include <list>
00044 #include <vector>
00045 
00046 class OcTree {
00047 public:
00048         typedef NormalEstimationValueClass ValueClass;
00049         typedef spatialaggregate::OcTree<float, ValueClass> Octree;
00050         typedef Octree* OctreePtr;
00051         typedef spatialaggregate::OcTreeNodeFixedCountAllocator<float, ValueClass> Allocator;
00052         typedef boost::shared_ptr<Allocator> AllocatorPtr;
00053         typedef algorithm::OcTreeSamplingMap<float, ValueClass> SamplingMap;
00054         typedef spatialaggregate::OcTreeNode<float, ValueClass>* NodePtr;
00055         typedef spatialaggregate::OcTreeKey<float, ValueClass> OctreeKey;
00056         typedef std::vector<NodePtr> NodePointers;
00057         typedef std::list<NodePtr> NodePointerList;
00058         typedef std::vector<int> PointIndices;
00059         typedef std::vector<PointIndices> NodeIdToPointIdxVector;
00060         typedef Eigen::Vector3f Vec3;
00061 
00062         OcTree(float minOctreeResolution, float rho_max, float principalVarFactor, float minPointsForNormal,
00063                         float curvThreshold, float curv2Threshold, float sqDistFactor, size_t numPoints) :
00064                 mOctreePtr(NULL), mOctreeDepth(0), mMinOctreeResolution(minOctreeResolution), mRho_max(rho_max),
00065                                 mPrincipalVarFactor(principalVarFactor), mMinPointsForNormal(minPointsForNormal), mCurvThreshold(
00066                                                 curvThreshold), mCurv2Threshold(curv2Threshold) , mSqDistFactor(sqDistFactor){
00067                 preAllocate(numPoints);
00068         }
00069 
00070         ~OcTree() {
00071                 if (mOctreePtr != NULL)
00072                         delete mOctreePtr;
00073         }
00074 
00075         void preAllocate(const size_t& numPoints);
00076 
00077         template<typename PointCloudType>
00078         void buildOctree(const PointCloudType& pointCloud);
00079 
00080         bool checkSamplingMap() const
00081         {
00082                 for(unsigned int depth = 0; depth <= mOctreeDepth; ++depth)
00083                 {
00084                         NodePointers octreeNodes(getNodesOnDepth(depth));
00085                         if(!checkOctreeNodes(octreeNodes))
00086                         {
00087                                 std::cout << "checkSamplingMap test failed on depth " << depth << " of " << mOctreeDepth << std::endl;
00088                                 return false;
00089                         }
00090                 }
00091                 return true;
00092         }
00093 
00094         bool checkGetAllLeafs() const
00095         {
00096                 NodePointers octreeNodes;
00097                 getAllLeafs(octreeNodes, mOctreePtr->root_);
00098                 return checkOctreeNodes(octreeNodes);
00099         }
00100 
00101         bool checkOctreeNodes(const NodePointers& nodePointers) const
00102         {
00103                 for(NodePointers::const_iterator np_it = nodePointers.begin(); np_it != nodePointers.end(); ++np_it)
00104                 {
00105                         if((*np_it)->value_.id >= mNodeIdToPointIdxVector.size())
00106                         {
00107                                 return false;
00108                         }
00109                 }
00110                 return true;
00111         }
00112 
00113         const unsigned int& getMaxDepth() const {
00114                 return mOctreeDepth;
00115         }
00116 
00117         const SamplingMap& getSamplingMap() const {
00118                 return mSamplingMap;
00119         }
00120 
00121         const NodePointerList& getNodeListOnDepth(const unsigned int& depth) const {
00122                 assert(depth <= mOctreeDepth);
00123                 return mSamplingMap.find(depth)->second;
00124         }
00125 
00126         NodePointers getNodesOnDepth(const unsigned int& depth) const {
00127                 assert(depth <= mOctreeDepth);
00128                 NodePointerList nodePointerList = mSamplingMap.find(depth)->second;
00129                 NodePointers nodePointers;
00130                 for(NodePointerList::const_iterator list_it = nodePointerList.begin(); list_it != nodePointerList.end(); ++list_it)
00131                 {
00132                         nodePointers.push_back(*list_it);
00133                 }
00134                 return nodePointers;
00135         }
00136 
00137         const OctreePtr& getOctreePtr() const
00138         {
00139                 return mOctreePtr;
00140         }
00141 
00142         const PointIndices& getPointsFromNodeId(const unsigned int& nodeId) const {
00143                 assert(nodeId < mNodeIdToPointIdxVector.size());
00144                 return mNodeIdToPointIdxVector[nodeId];
00145         }
00146 
00147         const PointIndices& getPointsFromNodePtr(const NodePtr& nodePtr) const {
00148                 const unsigned int& nodeId = nodePtr->value_.id;
00149                 return getPointsFromNodeId(nodeId);
00150         }
00151 
00152         float getCellSizeFromDepth(const unsigned int& depth) const {
00153                 return mOctreePtr->volumeSizeForDepth((int) depth);
00154         }
00155 
00156         void findFinestNormal(Vec3& normal, const Vec3& point) const{//TODO handle Vec3f -> Mat41
00157                 NodePtr nodePtr = mOctreePtr->root_->findRepresentative(Eigen::Vector4f(point(0), point(1), point(2), 1.f), mMinOctreeResolution);
00158                 while(!nodePtr->value_.stable){//there must be a stable node (with normal) for every point, that comes from a surfel (stable node with normal)
00159                         nodePtr = nodePtr->parent_;
00160                 }
00161                 normal = nodePtr->value_.normal;
00162         }
00163 
00164         void getNeighboringNodes(NodePointers& neighborNodes, const NodePtr& node, const unsigned int& maxSearchDepth,
00165                         const float& neighborhoodSize = 1.f) const;
00166 
00167         void getNeighboringNodes(NodePointers& neighborNodes, const NodePtr& currNode, const unsigned int& maxSearchDepth,
00168                         const unsigned int& currDepth, const OctreeKey& minPos, const OctreeKey& maxPos) const;
00169 
00170         void getAllLeafs(NodePointers& leafNodes, const NodePtr& topNode) const;
00171 private:
00172         AllocatorPtr mAllocatorPtr;
00173         OctreePtr mOctreePtr;
00174         unsigned int mOctreeDepth;
00175         SamplingMap mSamplingMap;
00176         NodeIdToPointIdxVector mNodeIdToPointIdxVector;
00177 
00178         // parameters
00179         float mMinOctreeResolution;
00180         float mRho_max;
00181         float mPrincipalVarFactor;
00182         float mMinPointsForNormal;
00183         float mCurvThreshold;
00184         float mCurv2Threshold;
00185         float mSqDistFactor;
00186 };
00187 
00188 inline void OcTree::preAllocate(const size_t& numPoints) {
00189         mAllocatorPtr.reset(new Allocator(numPoints));
00190 }
00191 
00192 template<typename PointCloudType>
00193 void OcTree::buildOctree(const PointCloudType& pointCloud) {
00194         mNodeIdToPointIdxVector.clear();
00195         mNodeIdToPointIdxVector.reserve(pointCloud.points.size());
00196         mAllocatorPtr->reset();
00197 
00198         if (mOctreePtr)
00199                 delete mOctreePtr;
00200         Vec3 rootPos(0.f, 0.f, 0.f);
00201         mOctreePtr = new Octree(Eigen::Vector4f(rootPos(0), rootPos(1), rootPos(2), 1.f), mMinOctreeResolution, mRho_max, mAllocatorPtr);
00202         mOctreeDepth = 0;
00203         unsigned int idx = 0;
00204         for (unsigned int i = 0; i < pointCloud.points.size(); i++) {
00205                 if (isnan(pointCloud.points[i].x) || isinf(pointCloud.points[i].x))
00206                         continue;
00207 
00208                 if (isnan(pointCloud.points[i].y) || isinf(pointCloud.points[i].y))
00209                         continue;
00210 
00211                 if (isnan(pointCloud.points[i].z) || isinf(pointCloud.points[i].z))
00212                         continue;
00213                 Vec3 pos(pointCloud.points[i].getVector3fMap());
00214                 ValueClass val;
00215                 val.id = idx;
00216                 val.numPoints = 1;
00217                 val.summedSquares(0, 0) = pos(0) * pos(0); // xx
00218                 val.summedSquares(0, 1) = val.summedSquares(1, 0) = pos(0) * pos(1); // xy
00219                 val.summedSquares(0, 2) = val.summedSquares(2, 0) = pos(0) * pos(2); // xz
00220                 val.summedSquares(1, 1) = pos(1) * pos(1); // yy
00221                 val.summedSquares(1, 2) = val.summedSquares(2, 1) = pos(1) * pos(2); // yz
00222                 val.summedSquares(2, 2) = pos(2) * pos(2); // zz
00223                 val.summedPos(0) = pos(0);
00224                 val.summedPos(1) = pos(1);
00225                 val.summedPos(2) = pos(2);
00226                 NodePtr n;
00227                 if (mSqDistFactor > 0.f){
00228                         float sqdist = val.summedSquares(0, 0) + val.summedSquares(1, 1) + val.summedSquares(2, 2);
00229                         float minResolution = std::max(mMinOctreeResolution, mSqDistFactor * sqdist);
00230                         n = mOctreePtr->addPoint(pos(0), pos(1), pos(2), val, mOctreePtr->depthForVolumeSize(minResolution));
00231                 }
00232                 else
00233                         n = mOctreePtr->addPoint(pos(0), pos(1), pos(2), val, mOctreePtr->depthForVolumeSize(mMinOctreeResolution));
00234                 if (n->value_.id == idx) {
00235                         mNodeIdToPointIdxVector.push_back(std::vector<int>(1, i));
00236                         idx++;
00237                 } else {
00238                         assert(n->value_.id <= pointCloud.points.size());
00239                         mNodeIdToPointIdxVector[n->value_.id].push_back(i);
00240                 }
00241                 if ((unsigned int)n->depth_ > mOctreeDepth)
00242                         mOctreeDepth = (unsigned int)n->depth_;
00243         }
00244 
00245         assert(checkGetAllLeafs());
00246 
00247         mSamplingMap.clear();
00248         mSamplingMap = algorithm::downsampleOcTree(*mOctreePtr, true, mOctreeDepth);
00249         for (unsigned int d = 0; d <= mOctreeDepth; d++) {
00250                 const NodePointerList& octreeLayer = mSamplingMap[d];
00251                 float principalVariance = mPrincipalVarFactor * getCellSizeFromDepth(d);
00252                 principalVariance *= principalVariance;
00253                 for(NodePointerList::const_iterator np_it = octreeLayer.begin(); np_it != octreeLayer.end(); ++np_it)
00254                 {
00255                         if (!(*np_it)->value_.stable)
00256                         {
00257                                 calculateNormal((*np_it), Vec3(0.f, 0.f, 0.f), mMinPointsForNormal, mCurvThreshold, mCurv2Threshold, principalVariance);
00258                         }
00259                 }
00260         }
00261 
00262         assert(checkSamplingMap());
00263 }
00264 
00265 inline void OcTree::getNeighboringNodes(NodePointers& neighborNodes, const NodePtr& node, const unsigned int& maxSearchDepth,
00266                 const float& neighborhoodSize) const {
00267         Vec3 size;
00268         size(0) = node->max_key_.getPosition(node->tree_)(0) - node->min_key_.getPosition(node->tree_)(0);
00269         size(1) = node->max_key_.getPosition(node->tree_)(1) - node->min_key_.getPosition(node->tree_)(1);
00270         size(2) = node->max_key_.getPosition(node->tree_)(2) - node->min_key_.getPosition(node->tree_)(2);
00271         float minPosX = node->pos_key_.getPosition(node->tree_)(0) - size(0) * neighborhoodSize;
00272         float minPosY = node->pos_key_.getPosition(node->tree_)(1) - size(1) * neighborhoodSize;
00273         float minPosZ = node->pos_key_.getPosition(node->tree_)(2) - size(2) * neighborhoodSize;
00274         OctreeKey minPos(minPosX, minPosY, minPosZ, node->tree_);
00275         float maxPosX = node->pos_key_.getPosition(node->tree_)(0) + size(0) * neighborhoodSize;
00276         float maxPosY = node->pos_key_.getPosition(node->tree_)(1) + size(1) * neighborhoodSize;
00277         float maxPosZ = node->pos_key_.getPosition(node->tree_)(2) + size(2) * neighborhoodSize;
00278         OctreeKey maxPos(maxPosX, maxPosY, maxPosZ, node->tree_);
00279         getNeighboringNodes(neighborNodes, mOctreePtr->root_, maxSearchDepth, 0, minPos, maxPos);
00280 }
00281 
00282 inline void OcTree::getNeighboringNodes(NodePointers& neighborNodes, const NodePtr& currNode, const unsigned int& maxSearchDepth,
00283                 const unsigned int& currDepth, const OctreeKey& minPos, const OctreeKey& maxPos) const {
00284         if (currNode->type_ == spatialaggregate::OCTREE_LEAF_NODE || currDepth == maxSearchDepth) {
00285                 if (currNode->overlap(minPos, maxPos) && !currNode->value_.nodeQuerried) {
00286                         neighborNodes.push_back(currNode);
00287                 }
00288         } else {
00289                 for (unsigned int i=0; i<8; ++i){
00290                         if (!currNode->children_[i]){
00291                                 continue;
00292                         }
00293                         if(currNode->children_[i]->overlap(minPos, maxPos))
00294                                 getNeighboringNodes(neighborNodes, currNode->children_[i], maxSearchDepth, currDepth+1, minPos, maxPos);
00295                 }
00296         }
00297 }
00298 
00299 inline void OcTree::getAllLeafs(NodePointers& leafNodes, const NodePtr& topNode) const{
00300         if(topNode->type_ == spatialaggregate::OCTREE_LEAF_NODE){
00301                 leafNodes.push_back(topNode);
00302         }
00303         else {
00304                 // for all siblings
00305                 // call getAllLeafs
00306                 for(unsigned int i = 0; i < 8; i++){
00307                         if(!topNode->children_[i])
00308                                 continue;
00309                         getAllLeafs(leafNodes, topNode->children_[i]);
00310                 }
00311         }
00312 }
00313 #endif /* OCTREE_H_ */


structure_coloring_fkie
Author(s): Bastian Gaspers
autogenerated on Sun Jan 5 2014 11:38:09