40 #include <unordered_map> 
   44 #include "Eigen/Eigenvalues" 
   51         nbSample{Parametrizable::get<std::size_t>(
"nbSample")}
 
   55                 const std::uint8_t tnm = this->
template get<std::uint8_t>(
"torqueNorm");
 
   56                 normalizationMethod = TorqueNormMethod(tnm);
 
   60                 normalizationMethod = TorqueNormMethod::Lavg;
 
   69         inPlaceFilter(output);
 
   76         const std::size_t featDim(cloud.
features.rows());
 
   81         if(nbSample >= nbPoints)
 
   86                 throw InvalidField(
"OrientNormalsDataPointsFilter: Error, cannot find normals in descriptors.");
 
   90         std::vector<std::size_t> keepIndexes;
 
   91         keepIndexes.resize(nbSample);
 
   95         std::vector<std::size_t> candidates ;
 
   96         candidates.resize(nbPoints);
 
   98         for (std::size_t i = 0; i < nbPoints; ++i) candidates[i] = i;
 
  100         const std::size_t nbCandidates = candidates.size();
 
  104         for(std::size_t i = 0; i < featDim - 1; ++i) center(i) = 
T(0.);
 
  106         for (std::size_t i = 0; i < nbCandidates; ++i)
 
  107                 for (std::size_t f = 0; f < 3; ++f)
 
  108                         center(f) += cloud.
features(f,candidates[i]);
 
  110         for(std::size_t i = 0; i < 3; ++i) center(i) /= 
T(nbCandidates);
 
  115         if(normalizationMethod == TorqueNormMethod::L1)
 
  119         else if(normalizationMethod == TorqueNormMethod::Lavg)
 
  122                 for (std::size_t i = 0; i < nbCandidates; ++i)
 
  123                         Lnorm += (cloud.
features.col(candidates[i]).head(3) - center).norm();
 
  124                 Lnorm /= nbCandidates;
 
  126         else if(normalizationMethod == TorqueNormMethod::Lmax)  
 
  130                 const Vector3 radii = maxValues.head(3) - minValues.head(3);
 
  132                 Lnorm = radii.maxCoeff() / 2.; 
 
  136         auto computeCovariance = [Lnorm, nbCandidates, &cloud, ¢er, &normals, &candidates](
Matrix66 & cov) -> 
void {
 
  138                         Eigen::Matrix<T, 6, Eigen::Dynamic> F(6, nbCandidates);
 
  140                         for(std::size_t i = 0; i < nbCandidates; ++i)
 
  142                                 const Vector3 p = cloud.features.col(candidates[i]).head(3) - center; 
 
  143                                 const Vector3 ni = normals.col(candidates[i]).head(3);
 
  146                                 F.template block<3, 1>(0, i) = (1. / Lnorm) * p.cross(ni);
 
  148                                 F.template block<3, 1>(3, i) = ni;
 
  152                         cov = F * F.transpose(); 
 
  156         computeCovariance(covariance);
 
  158         Eigen::EigenSolver<Matrix66> solver(covariance);                
 
  159         const Matrix66  eigenVe = solver.eigenvectors().real();
 
  160         const Vector6   eigenVa = solver.eigenvalues().real();
 
  164         std::vector<Vector6, Eigen::aligned_allocator<Vector6>> v; 
 
  165         v.resize(nbCandidates);
 
  167         for(std::size_t i = 0; i < nbCandidates; ++i)
 
  169                 const Vector3 p = cloud.features.col(candidates[i]).head(3) - center; 
 
  170                 const Vector3 ni = normals.col(candidates[i]).head(3);
 
  172                 v[i].template block<3, 1>(0, 0) = (1. / Lnorm) * p.cross(ni);
 
  173                 v[i].template block<3, 1>(3, 0) = ni;
 
  177         std::vector<std::list<std::pair<int, T>>> L; 
 
  181         auto comp = [](
const std::pair<int, T>& p1, 
const std::pair<int, T>& p2) -> 
bool {
 
  182                         return p1.second > p2.second;
 
  185         for(std::size_t k = 0; k < 6; ++k)
 
  187                 for(std::size_t i = 0; i < nbCandidates; ++i )
 
  189                         L[k].push_back(std::make_pair(i, std::fabs( v[i].dot(eigenVe.template block<6,1>(0, k)) )));
 
  195         std::vector<T> t(6, 
T(0.)); 
 
  196         std::vector<bool> sampledPoints(nbCandidates, 
false); 
 
  199         for(std::size_t i = 0; i < nbSample; ++i)
 
  206                 for (std::size_t i = 0; i < 6; ++i)
 
  212                 while(sampledPoints[L[k].front().first])
 
  216                 const std::size_t idToKeep = 
static_cast<std::size_t
>(L[k].front().first);
 
  219                 sampledPoints[idToKeep] = 
true; 
 
  222                 for (std::size_t k = 0; k < 6; ++k)
 
  224                         const T magnitude = v[idToKeep].dot(eigenVe.template block<6, 1>(0, k));
 
  225                         t[k] += (magnitude * magnitude);
 
  228                 keepIndexes[i] = candidates[idToKeep];
 
  233         std::unordered_map<std::size_t, std::size_t> mapidx;
 
  237         for(std::size_t 
id : keepIndexes)
 
  243                 cloud.swapCols(idx, 
id);        
 
  249         cloud.conservativeResize(nbSample);
 
  254 template <
typename T>
 
  257         Vector eigenVa = Vector::Identity(6, 1);                
 
  259         Eigen::EigenSolver<Matrix66> solver(cov);               
 
  260         eigenVa = solver.eigenvalues().real();
 
  262         return eigenVa.maxCoeff() / eigenVa.minCoeff();