/******************************************************************** ** Image Component Library (ICL) ** ** ** ** Copyright (C) 2006-2013 CITEC, University of Bielefeld ** ** Neuroinformatics Group ** ** Website: www.iclcv.org and ** ** http://opensource.cit-ec.de/projects/icl ** ** ** ** File : ICLGeom/src/ICLGeom/PointCloudSegment.cpp ** ** Module : ICLGeom ** ** Authors: Christof Elbrechter, Andre Ueckermann ** ** ** ** ** ** GNU LESSER GENERAL PUBLIC LICENSE ** ** This file may be used under the terms of the GNU Lesser General ** ** Public License version 3.0 as published by the ** ** ** ** Free Software Foundation and appearing in the file LICENSE.LGPL ** ** included in the packaging of this file. Please review the ** ** following information to ensure the license requirements will ** ** be met: http://www.gnu.org/licenses/lgpl-3.0.txt ** ** ** ** The development of this software was supported by the ** ** Excellence Cluster EXC 277 Cognitive Interaction Technology. ** ** The Excellence Cluster EXC 277 is a grant of the Deutsche ** ** Forschungsgemeinschaft (DFG) in the context of the German ** ** Excellence Initiative. ** ** ** ********************************************************************/ #include namespace icl{ namespace geom{ PointCloudSegment::PointCloudSegment(int dim, bool withColors): PointCloudObject(dim,false,withColors), featuresComputed(false), numPoints(0) { } PointCloudSegment::PointCloudSegment(geom::PointCloudObject &obj): PointCloudObject(1, obj.supports(PointCloudObjectBase::Normal), obj.supports(PointCloudObjectBase::RGBA32f)), featuresComputed(false){ init(obj, std::vector*>()); } PointCloudSegment::PointCloudSegment(geom::PointCloudObject &obj, const std::vector &indices): PointCloudObject(1, obj.supports(PointCloudObjectBase::Normal), obj.supports(PointCloudObjectBase::RGBA32f)), featuresComputed(false){ std::vector*> v(1,&indices); init(obj, v); } PointCloudSegment::PointCloudSegment(geom::PointCloudObject &obj, const std::vector*> &indices): PointCloudObject(1, obj.supports(PointCloudObjectBase::Normal), obj.supports(PointCloudObjectBase::RGBA32f)), featuresComputed(false){ init(obj,indices); } Mat PointCloudSegment::computeEigenVectorFrame() const throw (utils::ICLException){ const math::Vec3 &x = eigenvectors[0]; const math::Vec3 &y = eigenvectors[1]; Vec z = math::cross(x.resize<1,4>(1), y.resize<1,4>(1)); return Mat(x[0], y[0], z[0], mean[0], x[1], y[1], z[1], mean[1], x[2], y[2], z[2], mean[2], 0,0,0,1); } /// returns week pointer to the i-th child (already casted to PointCloudSegment type) utils::SmartPtr PointCloudSegment::getSubSegment(int i) throw (utils::ICLException){ if(i<0 || i >= getChildCount()){ throw utils::ICLException("PointCloudSegment:getSubSegment: invalid index!"); } utils::SmartPtr obj = getChildPtr(i); if(!obj){ throw utils::ICLException("PointCloudSegment:getSubSegment: selected sub-segment is null (which should not happen)"); } PointCloudSegment *p = dynamic_cast(obj.get()); if(!p) throw utils::ICLException("PointCloudSegment::getSubSegment: " "given child index does not refer to an actual " "PointCloudSegment instance! (to avoid undefined behaviour " "in further processing steps, this exception is thrown)"); return obj; // implicit smart-pointer cast should carry referrence conter //explicit cast//utils::SmartPtr(p,false); } static inline void copy_util(core::DataSegment s, core::DataSegment d, const std::vector *> &sidxs){ if(!sidxs.empty()){ int k = 0; for(size_t i=0;i &v = *sidxs[i]; for(size_t j=0;j Mat3; typedef math::FixedColVector Vec3; if(featuresComputed) return; math::Vec3 m(0,0,0); math::Mat3 C(0,0,0, 0,0,0, 0,0,0); AABB aabb = { Vec3(1.e38, 1.e38, 1.e38), Vec3(-1.e38, -1.e38, -1.e38) }; size_t n = 0; if(isParent()){ // update features of children first for(int i=0;iupdateFeatures(); } for(int i=0;igetDim(); // update bounding box const AABB &a = child->aabb; for(int j=0;j<3;++j){ if(a.min[j] < aabb.min[j]) aabb.min[j] = a.min[j]; if(a.max[j] > aabb.max[j]) aabb.max[j] = a.max[j]; } // compute moment matrix xx of child math::Mat3 xx (child->covariance); const math::Vec3& mc = child->mean; for(int y=0;y<3;++y){ for(int x=0;x<3;++x){ xx(x,y) += mc[x] * mc[y]; } } // update moments + mean C += xx * float(nc); m += child->mean * float(nc); n += nc; } }else{ // compute features!! n = getDim(); core::DataSegment xyz = selectXYZ(); for(size_t i=0;i aabb.max[d]) aabb.max[d] = v[d]; } // compute moments for(int y=0;y<3;++y){ for(int x=0;x<3;++x){ C(x,y) += v[x] * v[y]; } } // compute mean m += v; } } if (n > 0) { m *= 1./n; C *= 1./n; } this->numPoints = n; this->mean = m; this->aabb = aabb; // covariance = - mm^t for(int y=0;y<3;++y){ for(int x=0;x<3;++x){ C(x,y) -= m[x] * m[y]; } } this->covariance = C; // compute eigenvectors of covariance C try{ Mat3 evec; Vec3 eval; C.eigen(evec,eval); this->eigenvectors[0] = evec.col(0); this->eigenvectors[1] = evec.col(1); this->eigenvectors[2] = evec.col(2); this->eigenvalues = eval; }catch(utils::ICLException &){ Vec3 vecZero(0,0,0); this->eigenvalues = Vec3(1,1,1); this->mean = (aabb.min + aabb.max)*0.5; for(int i=0;i<3;++i){ this->eigenvectors[i] = vecZero; this->eigenvectors[i][i] = 1; } } featuresComputed = true; } void PointCloudSegment::init(geom::PointCloudObject &obj, const std::vector *> &indices){ if(!indices.empty()){ int n=0; for(size_t i=0;isize(); } setSize(utils::Size(n,1)); }else{ setSize(obj.getSize()); // we leave it organized! } copy_util(obj.selectXYZH(), selectXYZH(), indices); if(supports(Normal)){ copy_util(obj.selectNormal(), selectNormal(), indices); } if(supports(RGBA32f)){ copy_util(obj.selectRGBA32f(), selectRGBA32f(), indices); } updateFeatures(); } PointCloudSegment *PointCloudSegment::copy() const{ return new PointCloudSegment(*this); } static void count_points_recursive(PointCloudSegmentPtr p, int &n){ if(p->isParent()){ for(int i=0;igetNumSubSegments();++i){ count_points_recursive(p->getSubSegment(i),n); } }else{ n += p->getDim(); } } static void copy_points_recursive(PointCloudSegmentPtr p, PointCloudSegmentPtr dst, int &offs){ if(p->isParent()){ for(int i=0;igetNumSubSegments();++i){ copy_points_recursive(p->getSubSegment(i),dst,offs); } }else{ const core::DataSegment sxyz = p->selectXYZH(); const core::DataSegment srgb = p->selectRGBA32f(); core::DataSegment dxyz = dst->selectXYZH(); core::DataSegment drgb = dst->selectRGBA32f(); for(int i=0;imean = p->mean; c->eigenvectors[0] = p->eigenvectors[0]; c->eigenvectors[1] = p->eigenvectors[1]; c->eigenvectors[2] = p->eigenvectors[2]; c->eigenvalues = p->eigenvalues; c->numPoints = p->numPoints; c->aabb = p->aabb; return c; } utils::SmartPtr PointCloudSegment::flatten() const{ PointCloudSegmentPtr p(const_cast(this),false); return flatten_segment_hierarcy(p); } static void collect_children_recursive(std::vector &v, PointCloudSegmentPtr seg){ v.push_back(seg); if(seg->isParent()){ for(int i=0;igetNumSubSegments();++i){ collect_children_recursive(v,seg->getSubSegment(i)); } } } /// returns a vector containing this and all recursive children std::vector PointCloudSegment::extractThisAndChildren() const{ std::vector v; collect_children_recursive(v,PointCloudSegmentPtr(const_cast(this),false)); return v; } } }