39 #include <unordered_map>
50 nbSample{Parametrizable::get<std::size_t>(
"nbSample")},
51 seed{Parametrizable::get<std::size_t>(
"seed")},
52 epsilon{Parametrizable::get<T>(
"epsilon")},
53 nbBucket{std::size_t(ceil(2.0 * M_PI / epsilon) * ceil(M_PI / epsilon))}
62 inPlaceFilter(output);
72 const std::size_t featDim = cloud.
features.rows();
75 std::cerr <<
"ERROR: NormalSpaceDataPointsFilter does not support 2D point cloud yet (does nothing)" << std::endl;
81 if(nbSample >= std::size_t(nbPoints))
86 throw InvalidField(
"OrientNormalsDataPointsFilter: Error, cannot find normals in descriptors.");
90 std::mt19937 gen(seed);
93 std::vector<std::vector<int> > idBuckets;
94 idBuckets.resize(nbBucket);
96 std::vector<std::size_t> keepIndexes;
97 keepIndexes.reserve(nbSample);
100 std::vector<std::size_t> randIdcs(nbPoints);
101 std::iota(randIdcs.begin(), randIdcs.end(), 0);
102 std::shuffle(randIdcs.begin(), randIdcs.end(), gen);
105 for (
auto randIdx : randIdcs)
108 assert(normals.col(randIdx).head(3).norm() >= 1.0-0.00001);
109 assert(normals.col(randIdx).head(3).norm() <= 1.0+0.00001);
111 assert((normals(2,randIdx) <= 1.0) && (normals(2,randIdx) >= -1.0));
114 const T theta = std::acos(normals(2, randIdx));
116 const T phi = std::fmod(std::atan2(normals(1, randIdx), normals(0, randIdx)) + 2. * M_PI, 2. * M_PI);
119 assert(bucketIdx(theta, phi) < nbBucket);
120 idBuckets[bucketIdx(theta, phi)].push_back(randIdx);
124 idBuckets.erase(std::remove_if(idBuckets.begin(), idBuckets.end(),
125 [](
const std::vector<int>& bucket) { return bucket.empty(); }),
129 for (std::size_t i=0; i<nbSample; i++)
132 std::uniform_int_distribution<std::size_t> uniBucket(0,idBuckets.size()-1);
133 std::size_t curBucketIdx = uniBucket(gen);
134 std::vector<int>& curBucket = idBuckets[curBucketIdx];
137 int idToKeep = curBucket[curBucket.size()-1];
138 curBucket.pop_back();
139 keepIndexes.push_back(
static_cast<std::size_t
>(idToKeep));
142 if (curBucket.empty()) {
143 idBuckets.erase(idBuckets.begin()+curBucketIdx);
149 std::unordered_map<std::size_t, std::size_t> mapidx;
153 for(std::size_t
id : keepIndexes)
168 template <
typename T>
172 assert( (theta >= 0.0) && (theta <=
static_cast<T>(M_PI)) &&
"Theta not in [0, Pi]");
173 assert( (phi >= 0) && (phi <= 2*
static_cast<T>(M_PI)) &&
"Phi not in [0, 2Pi]");
176 if (theta ==
static_cast<T>(M_PI)) { theta = 0.0; };
178 if (phi == 2*
static_cast<T>(M_PI)) { phi = 0.0; };
180 return static_cast<std::size_t
>( floor(theta/epsilon) * ceil(2.0*M_PI/epsilon) + floor(phi/epsilon) );