/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ #ifndef __VCGLIB_FITTING3 #define __VCGLIB_FITTING3 #include #include #include #include #include #include namespace vcg { /*! \brief compute the covariance matrix of a set of point It returns also the barycenter of the point set */ template void ComputeCovarianceMatrix(const std::vector > &pointVec, Point3 &barycenter, Eigen::Matrix &m) { // first cycle: compute the barycenter barycenter.SetZero(); typename std::vector< Point3 >::const_iterator pit; for( pit = pointVec.begin(); pit != pointVec.end(); ++pit) barycenter+= (*pit); barycenter/=pointVec.size(); // second cycle: compute the covariance matrix m.setZero(); Eigen::Matrix p; for(pit = pointVec.begin(); pit != pointVec.end(); ++pit) { ((*pit)-barycenter).ToEigenVector(p); m+= p*p.transpose(); // outer product } } /*! \brief Compute the plane best fitting a set of points The algorithm used is the classical Covariance matrix eigenvector approach. */ template void FitPlaneToPointSet(const std::vector< Point3 > & pointVec, Plane3 & plane) { Eigen::Matrix covMat = Eigen::Matrix::Zero(); Point3 b; ComputeCovarianceMatrix(pointVec,b,covMat); Eigen::SelfAdjointEigenSolver > eig(covMat); Eigen::Matrix eval = eig.eigenvalues(); Eigen::Matrix evec = eig.eigenvectors(); eval = eval.cwiseAbs(); int minInd; eval.minCoeff(&minInd); Point3 d; d[0] = evec(0,minInd); d[1] = evec(1,minInd); d[2] = evec(2,minInd); plane.Init(b,d); } /*! \brief compute the weighted covariance matrix of a set of point It returns also the weighted barycenter of the point set. When computing the covariance matrix the weights are applied to the points transposed to the origin. */ template void ComputeWeightedCovarianceMatrix(const std::vector > &pointVec, const std::vector &weightVec, Point3 &bp, Eigen::Matrix &m) { assert(pointVec.size() == weightVec.size()); // First cycle: compute the weighted barycenter bp.SetZero(); S wSum=0; typename std::vector< Point3 >::const_iterator pit; typename std::vector< S>::const_iterator wit; for( pit = pointVec.begin(),wit=weightVec.begin(); pit != pointVec.end(); ++pit,++wit) { bp+= (*pit)*(*wit); wSum+=*wit; } bp /=wSum; // Second cycle: compute the weighted covariance matrix // The weights are applied to the points transposed to the origin. m.setZero(); Eigen::Matrix A; Eigen::Matrix p; for( pit = pointVec.begin(),wit=weightVec.begin(); pit != pointVec.end(); ++pit,++wit) { (((*pit)-bp)*(*wit)).ToEigenVector(p); m+= p*p.transpose(); // outer product } m/=wSum; } /*! \brief Compute the plane best fitting a set of points The algorithm used is the classical Covariance matrix eigenvector approach. */ template void WeightedFitPlaneToPointSet(const std::vector< Point3 > & pointVec, const std::vector &weightVec, Plane3 & plane) { Eigen::Matrix covMat = Eigen::Matrix::Zero(); Point3 b; ComputeWeightedCovarianceMatrix(pointVec,weightVec, b,covMat); Eigen::SelfAdjointEigenSolver > eig(covMat); Eigen::Matrix eval = eig.eigenvalues(); Eigen::Matrix evec = eig.eigenvectors(); eval = eval.cwiseAbs(); int minInd; eval.minCoeff(&minInd); Point3 d; d[0] = evec(0,minInd); d[1] = evec(1,minInd); d[2] = evec(2,minInd); plane.Init(b,d); } } // end namespace #endif