28 #ifndef NORM_EST_CGAL_OMP_H
29 #define NORM_EST_CGAL_OMP_H
31 #if defined(_OPENMP) && defined(USE_OPENMP_FOR_NORMEST)
35 #include <CGAL/Aff_transformation_3.h>
36 #include <CGAL/Fuzzy_sphere.h>
37 #include <CGAL/Kd_tree.h>
38 #include <CGAL/Orthogonal_k_neighbor_search.h>
39 #include <CGAL/Point_3.h>
40 #include <CGAL/Search_traits_3.h>
41 #include <CGAL/Simple_cartesian.h>
42 #include <CGAL/Vector_3.h>
86 typedef CGAL::Simple_cartesian<float>
Kernel;
87 typedef typename CGAL::Point_3<Kernel>
Point3;
88 typedef typename CGAL::Vector_3<Kernel>
Vector3;
89 typedef typename CGAL::Aff_transformation_3<Kernel>
Matrix3;
90 typedef typename CGAL::Search_traits_3<Kernel>
TreeTraits;
92 typedef typename CGAL::Orthogonal_k_neighbor_search<TreeTraits>
94 typedef typename CGAL::Kd_tree<TreeTraits>
Tree;
127 set_default_parameters();
142 return lower_neighbor_bound_neighbors;
145 return lower_neighbor_bound_neighbors;
159 int neighborhood_type =
KNN,
160 float neighborhood_size = 200) {
161 std::cout <<
"Normal_Estimation ";
164 std::cout <<
"Points ";
165 switch (neighborhood_type) {
168 std::cout << (int)neighborhood_size <<
std::endl;
169 points_knn((
int)neighborhood_size);
172 std::cout <<
"radius=";
173 std::cout << neighborhood_size <<
std::endl;
174 points_radius(neighborhood_size);
177 std::cout <<
"Parameter Error : bad neighborhood type"
183 std::cout <<
"Unif ";
184 switch (neighborhood_type) {
187 std::cout << (int)neighborhood_size <<
std::endl;
188 unif_knn((
int)neighborhood_size);
191 std::cout <<
"radius=";
192 std::cout << neighborhood_size <<
std::endl;
193 unif_radius(neighborhood_size);
196 std::cout <<
"Parameter Error : bad neighborhood type"
202 std::cout <<
"Cubes ";
203 switch (neighborhood_type) {
206 std::cout << (int)neighborhood_size <<
std::endl;
207 cubes_knn((
int)neighborhood_size);
210 std::cout <<
"radius=";
211 std::cout << neighborhood_size <<
std::endl;
212 cubes_radius(neighborhood_size);
215 std::cout <<
"Parameter Error : bad neighborhood type"
221 std::cout <<
"Parameter Error : bad method" <<
std::endl;
228 int lower_neighbor_bound_neighbors;
236 float small_radius_factor;
242 std::vector<Point3> &pts;
243 std::vector<Vector3> &nls;
248 void set_default_parameters() {
253 tol_angle_rad = 0.79;
254 small_radius_factor = 4;
256 lower_neighbor_bound_neighbors = 10;
266 inline void generate_rotation_matrix(std::vector<Matrix3> &rotMat,
267 std::vector<Matrix3> &rotMatInv,
272 if (rotations == 0) {
273 Matrix3 rMat(1, 0, 0, 0, 1, 0, 0, 0, 1);
274 rotMat.push_back(rMat);
275 rotMatInv.push_back(rMat);
277 for (
int i = 0; i < rotations; i++) {
278 float theta = (rand() + 0.f) / RAND_MAX * 2 * 3.14159265f;
279 float phi = (rand() + 0.f) / RAND_MAX * 2 * 3.14159265f;
280 float psi = (rand() + 0.f) / RAND_MAX * 2 * 3.14159265f;
281 Matrix3 Rt(1, 0, 0, 0, cos(theta), -sin(theta), 0, sin(theta),
283 Matrix3 Rph(cos(phi), 0, sin(phi), 0, 1, 0, -sin(phi), 0,
285 Matrix3 Rps(cos(psi), -sin(psi), 0, sin(psi), cos(psi), 0, 0, 0,
287 Matrix3 Rtinv(1, 0, 0, 0, cos(theta), sin(theta), 0,
288 -sin(theta), cos(theta));
289 Matrix3 Rphinv(cos(phi), 0, -sin(phi), 0, 1, 0, sin(phi), 0,
291 Matrix3 Rpsinv(cos(psi), sin(psi), 0, -sin(psi), cos(psi), 0, 0,
295 Matrix3 rMatInv = Rpsinv * Rphinv * Rtinv;
296 rotMat.push_back(rMat);
297 rotMatInv.push_back(rMatInv);
307 inline void generate_random_points_vector(std::vector<Point3> &
points,
309 points.resize(point_number);
310 for (
int i = 0; i < point_number; i++) {
313 x = ((rand() + 0.f) / RAND_MAX) * 2 - 1;
314 y = ((rand() + 0.f) / RAND_MAX) * 2 - 1;
315 z = ((rand() + 0.f) / RAND_MAX) * 2 - 1;
316 }
while (x * x + y * y + z * z > 1);
327 inline void generate_random_int_vector(std::vector<int> &vecInt,
329 vecInt.resize(point_number);
330 for (
int i = 0; i < point_number; i++) {
344 inline void list_of_triplets(std::vector<Vector3> &triplets,
345 const int &number_of_points,
346 const unsigned int &plane_number,
347 std::vector<int> &vecInt) {
354 unsigned long long total_comb = number_of_points;
355 total_comb *= (number_of_points - 1);
356 total_comb *= (number_of_points - 2);
359 std::vector<unsigned long long> tab_binome_3(number_of_points + 1);
360 std::vector<unsigned long long> tab_binome_2(number_of_points + 1);
362 for (
int i = 0; i < number_of_points + 1; i++) {
364 tab_binome_3[i] = tab_binome_3[i - 1] * i / (i - 3);
371 tab_binome_2[i] = tab_binome_2[i - 1] * i / (i - 2);
379 std::vector<unsigned long long> comb_idx(plane_number);
380 for (
int i = 0; i < plane_number; i++) {
381 comb_idx[i] = i % total_comb;
383 if (total_comb < RAND_MAX) {
384 std::map<int, int> table_next;
385 for (
int i = 0; i < plane_number; i++) {
386 int temp_idx = vecInt[i % vecInt.size()] % total_comb;
387 if (temp_idx < plane_number) {
388 int temp = comb_idx[i];
389 comb_idx[i] = comb_idx[temp_idx];
390 comb_idx[temp_idx] = temp;
392 std::map<int, int>::iterator itmap =
393 table_next.find(temp_idx);
394 if (itmap != table_next.end()) {
395 int temp = comb_idx[i];
396 comb_idx[i] = itmap->second;
397 itmap->second = temp;
399 comb_idx[i] = temp_idx;
400 table_next.insert(std::pair<int, int>(temp_idx, i));
405 unsigned long long ref_RAND_MAX = RAND_MAX;
407 while (ref_RAND_MAX < total_comb) {
409 ref_RAND_MAX *= RAND_MAX;
411 std::map<unsigned long long, unsigned long long> table_next;
413 for (
int i = 0; i < plane_number; i++) {
415 unsigned long long random_int = vecInt[pos % vecInt.size()];
417 for (
int j = 0; j < size_test; j++) {
419 ((
unsigned long long)vecInt[pos % vecInt.size()]) *
424 random_int = random_int % total_comb;
425 if (random_int < plane_number) {
426 int temp = comb_idx[i];
427 comb_idx[i] = comb_idx[random_int];
428 comb_idx[random_int] = temp;
430 std::map<unsigned long long, unsigned long long>::iterator
431 itmap = table_next.find(random_int);
432 if (itmap != table_next.end()) {
433 int temp = comb_idx[i];
434 comb_idx[i] = itmap->second;
435 itmap->second = temp;
437 comb_idx[i] = random_int;
439 std::pair<
unsigned long long,
440 unsigned long long>(random_int, i));
447 triplets.resize(plane_number);
448 for (
int pos = 0; pos < plane_number; pos++) {
450 unsigned long long idx = comb_idx[pos];
452 while (tab_binome_3[pos_temp] <= idx) {
457 idx -= tab_binome_3[pos_temp];
461 triplets[pos] =
Vector3(comb[0], comb[1], comb[2]);
466 while (tab_binome_2[pos_temp] <= idx) {
471 idx -= tab_binome_2[pos_temp];
474 triplets[pos] =
Vector3(comb[0], comb[1], comb[2]);
479 while (pos_temp != idx) {
483 triplets[pos] =
Vector3(comb[0], comb[1], comb[2]);
493 inline void generate_cube_vector(std::vector<int> &cubes_idx,
int n) {
496 std::vector<float> probas(n_cubes * n_cubes * n_cubes);
497 float step = 2.f / n_cubes;
498 float xmin = -(n_cubes / 2.f) * step;
499 float ymin = -(n_cubes / 2.f) * step;
500 float zmin = -(n_cubes / 2.f) * step;
502 for (
int k = 0; k < n_cubes; k++) {
503 for (
int j = 0; j < n_cubes; j++) {
504 for (
int i = 0; i < n_cubes; i++) {
507 float x1 = xmin + i * step;
508 float y1 = ymin + j * step;
509 float z1 = zmin + k * step;
510 float x2 = x1 + step;
511 float y2 = y1 + step;
512 float z2 = z1 + step;
546 probas[i + j * n_cubes + k * n_cubes * n_cubes] = prob;
552 probas[0] /= sum_prob;
553 for (
int i = 1; i < n_cubes * n_cubes * n_cubes; i++) {
554 probas[i] /= sum_prob;
555 probas[i] += probas[i - 1];
560 for (
int i = 0; i < n; i++) {
561 float pos = (rand() + 0.f) / RAND_MAX;
563 int end = n_cubes * n_cubes * n_cubes - 1;
564 int temp = (begin + end) / 2;
565 while (temp != begin) {
566 if (probas[temp] < pos) {
571 temp = (begin + end) / 2;
586 inline void assign_points_to_cubes(std::vector<int> cubes[],
589 std::vector<Point3> &
points,
590 std::vector<Point3> &points2,
592 float step = 2.f / n_cubes * radius;
593 for (
unsigned int i = 0; i < points2.size(); i++) {
596 Point3 refPoint2 = refPoint;
597 refPoint2 = refPoint2.transform(rotMat);
610 cubes[x + y * n_cubes + z * n_cubes * n_cubes].push_back(i);
621 inline void generate_cubes_triplets(std::vector<Vector3> &triplets,
622 std::vector<int> cubes[],
623 std::vector<int> &cubes_idx,
624 std::vector<int> &vecInt) {
625 triplets.resize(n_planes);
628 std::vector<int>::iterator itcube = cubes_idx.begin();
629 std::vector<int>::iterator itint = vecInt.begin();
633 while (ittrip != triplets.end() && itcube != cubes_idx.end()) {
634 if (cubes[*itcube].
size() != 0) {
635 int new_idx = cubes[*itcube][(*itint) % cubes[*itcube].size()];
636 bool is_valid =
true;
637 for (
int i = 0; i < idx; i++) {
638 if (new_idx == coord[i]) {
643 coord[idx] = new_idx;
648 *ittrip =
Vector3(coord[0], coord[1], coord[2]);
656 while (ittrip != triplets.end()) {
657 int picked_points = 0;
658 while (picked_points < 3) {
659 int pos = rand() % (n_cubes * n_cubes * n_cubes);
660 if (cubes[pos].
size() == 0) {
663 int idx = rand() % cubes[pos].size();
664 bool is_valid =
true;
665 for (
int i = 0; i < picked_points; i++) {
666 if (cubes[pos][idx] == coord[i]) {
671 coord[picked_points] = cubes[pos][idx];
675 (*ittrip) =
Vector3(coord[0], coord[1], coord[2]);
687 inline void find_a_triplet(
Tree &tree,
692 int picked_points = 0;
694 while (picked_points < 3) {
701 x = ((rand() + 0.f) / RAND_MAX) * 2 - 1;
702 y = ((rand() + 0.f) / RAND_MAX) * 2 - 1;
703 z = ((rand() + 0.f) / RAND_MAX) * 2 - 1;
704 }
while (x * x + y * y + z * z > 1);
717 std::vector<Point3> points_search;
718 tree.search(std::back_inserter(points_search), s_query);
720 if (points_search.size() != 0) {
721 Point3 new_Point = points_search[rand() % points_search.size()];
722 bool is_valid =
true;
723 for (
int i = 0; i < picked_points; i++) {
724 if (new_Point == triplet(i)) {
729 triplet(picked_points) = new_Point;
747 inline void generate_list_of_triplets(std::vector<Triplet> &triplets,
753 std::vector<Point3> &
points,
754 std::vector<int> &vecInt) {
755 triplets.resize(plane_number);
759 std::vector<int>::iterator itint = vecInt.begin();
762 while (ittrip != triplets.end() && itpoints !=
points.end()) {
765 x = (*itpoints).x() * radius1 + pt.x();
766 y = (*itpoints).y() * radius1 + pt.y();
767 z = (*itpoints).z() * radius1 + pt.z();
772 std::vector<Point3> points_search;
773 tree.search(std::back_inserter(points_search), s_query);
776 if (points_search.size() != 0) {
778 points_search[(*itint) % points_search.size()];
779 bool is_valid =
true;
780 for (
int i = 0; i < idx; i++) {
781 if (new_point == (*ittrip)(i)) {
786 (*ittrip)(idx) = new_point;
799 while (ittrip != triplets.end()) {
800 find_a_triplet(tree, radius1, radius2, *ittrip, pt);
814 float normal_at_point(
const int d1,
816 std::vector<Point3> &
points,
818 std::vector<Vector3> &triplets,
819 std::vector<float> &conf_interv) {
826 float *votes =
new float[d1 * d2];
828 for (
int i = 0; i < d1; i++) {
829 for (
int j = 0; j < d2; j++) {
830 votes[i + j * d1] = 0;
831 votesV[i + j * d1] =
Vector3(0, 0, 0);
835 float max1 = 0, max2 = 0;
840 for (
int n_try = 0; n_try < n_planes; n_try++) {
841 int p0 = triplets[n_try][0];
842 int p1 = triplets[n_try][1];
843 int p2 = triplets[n_try][2];
848 Vector3 Pn = CGAL::cross_product(v1, v2);
849 Pn = Pn / sqrt(Pn * Pn);
850 if (Pn * (
points[p0] - CGAL::ORIGIN) > 0) {
855 phi = acos((
float)Pn[2]);
856 float dphi =
PI / n_phi;
858 posp = int(
floor((phi + dphi / 2.) * n_phi / PI));
860 if (posp == 0 || posp == n_phi) {
863 float theta = acos((
float)Pn[0] /
864 sqrt(
float(Pn[0] * Pn[0] + Pn[1] * Pn[1])));
869 float dtheta =
PI / (n_phi * sin(posp * dphi));
870 post = (int)(
floor((theta + dtheta / 2) / dtheta)) %
877 votes[post + posp * d1] += 1.;
878 votesV[post + posp * d1] = Pn + votesV[post + posp * d1];
880 max1 = votes[i1 + j1 * d1] / (n_try + 1);
881 max2 = votes[i2 + j2 * d1] / (n_try + 1);
882 votes_val = votes[post + posp * d1] / (n_try + 1);
884 if (votes_val > max1) {
891 }
else if (votes_val > max2 && post != i1 && posp != j1) {
897 if (max1 - conf_interv[n_try] > max2) {
902 nls[n] = votesV[i1 + j1 * d1] /
903 sqrt(votesV[i1 + j1 * d1] * votesV[i1 + j1 * d1]);
919 float normal_at_point(
const int d1,
923 std::vector<Triplet> &triplets,
924 std::vector<float> &conf_interv) {
925 if (points_size < 3) {
931 float *votes =
new float[d1 * d2];
933 for (
int i = 0; i < d1; i++) {
934 for (
int j = 0; j < d2; j++) {
935 votes[i + j * d1] = 0;
936 votesV[i + j * d1] =
Vector3(0, 0, 0);
940 float max1 = 0, max2 = 0;
945 for (
int n_try = 0; n_try < n_planes; n_try++) {
946 Point3 p0 = triplets[n_try](0);
947 Point3 p1 = triplets[n_try](1);
948 Point3 p2 = triplets[n_try](2);
952 Vector3 Pn = CGAL::cross_product(v1, v2);
953 Pn = Pn / sqrt(Pn * Pn);
954 if (Pn * (p0 - CGAL::ORIGIN) > 0) {
959 phi = acos((
float)Pn[2]);
960 float dphi =
PI / n_phi;
962 posp = int(
floor((phi + dphi / 2.) * n_phi / PI));
964 if (posp == 0 || posp == n_phi) {
967 float theta = acos((
float)Pn[0] /
968 sqrt(
float(Pn[0] * Pn[0] + Pn[1] * Pn[1])));
973 float dtheta =
PI / (n_phi * sin(posp * dphi));
974 post = (int)(
floor((theta + dtheta / 2) / dtheta)) %
981 votes[post + posp * d1] += 1.;
982 votesV[post + posp * d1] = Pn + votesV[post + posp * d1];
984 max1 = votes[i1 + j1 * d1] / (n_try + 1);
985 max2 = votes[i2 + j2 * d1] / (n_try + 1);
986 votes_val = votes[post + posp * d1] / (n_try + 1);
988 if (votes_val > max1) {
995 }
else if (votes_val > max2 && post != i1 && posp != j1) {
1001 if (max1 - conf_interv[n_try] > max2) {
1006 nls[n] = votesV[i1 + j1 * d1] /
1007 sqrt(votesV[i1 + j1 * d1] * votesV[i1 + j1 * d1]);
1022 inline Vector3 normal_selection(
int &rotations,
1023 std::vector<Vector3> &normals_vec,
1024 std::vector<float> &normals_conf) {
1025 std::vector<bool> normals_use(rotations);
1028 normals_use[0] =
true;
1029 for (
int i = 1; i < rotations; i++) {
1030 normals_use[i] =
true;
1031 if (normals_vec[0] * normals_vec[i] < 0) {
1032 normals_vec[i] = -normals_vec[i];
1037 switch (selection_type) {
1040 float confidence_final = 0;
1041 for (
int i = 0; i < rotations; i++) {
1042 if (normals_conf[i] > confidence_final) {
1043 confidence_final = normals_conf[i];
1044 normal_final = normals_vec[i];
1050 std::vector<std::pair<Vector3, float>> normals_fin;
1051 int number_to_test = rotations;
1052 while (number_to_test > 0) {
1056 for (
int i = 0; i < rotations; i++) {
1057 if (normals_use[i] && normals_conf[i] > max_conf) {
1058 max_conf = normals_conf[i];
1063 normals_fin.push_back(std::pair<Vector3, float>(
1064 normals_vec[idx] * normals_conf[idx],
1065 normals_conf[idx]));
1066 normals_use[idx] =
false;
1069 for (
int i = 0; i < rotations; i++) {
1070 if (normals_use[i] &&
1071 acos(normals_vec[idx] * normals_vec[i]) <
1073 normals_use[i] =
false;
1075 normals_fin.back().first =
1076 normals_fin.back().first +
1077 normals_vec[i] * normals_conf[i];
1078 normals_fin.back().second += normals_conf[i];
1083 normal_final = normals_fin[0].first;
1084 float conf_fin = normals_fin[0].second;
1085 for (
unsigned int i = 1; i < normals_fin.size(); i++) {
1086 if (normals_fin[i].second > conf_fin) {
1087 conf_fin = normals_fin[i].second;
1088 normal_final = normals_fin[i].first;
1094 normal_final = normals_conf[0] * normals_vec[0];
1095 for (
int i = 1; i < rotations; i++) {
1097 normal_final + normals_conf[i] * normals_vec[i];
1102 return normal_final / sqrt(normal_final * normal_final);
1111 void points_knn(
int neighbor_number) {
1113 srand((
unsigned int)time(
NULL));
1115 nls.resize(pts.size());
1118 const int d1 = 2 * n_phi;
1119 const int d2 = n_phi + 1;
1122 std::vector<Matrix3> rotMat;
1123 std::vector<Matrix3> rotMatInv;
1124 generate_rotation_matrix(rotMat, rotMatInv, n_rot * 200);
1134 std::vector<float> conf_interv(n_planes);
1135 for (
int i = 0; i < n_planes; i++) {
1136 conf_interv[i] = 2.f / std::sqrt(i + 1.f);
1139 std::vector<int> vecInt;
1140 generate_random_int_vector(vecInt, 1000000);
1143 std::vector<Vector3> trip;
1144 if (rotations <= 1) {
1145 list_of_triplets(trip, neighbor_number, n_planes, vecInt);
1148 list_of_triplets(trip, neighbor_number, rotations * n_planes,
1152 #if defined(_OPENMP) && defined(USE_OPENMP_FOR_NORMEST)
1153 #pragma omp parallel
1155 Tree tree(pts.begin(), pts.end());
1156 #pragma omp for schedule(guided)
1158 Tree tree(pts.begin(), pts.end());
1160 for (
int n = 0; n < (int)pts.size(); n++) {
1161 std::vector<Point3>
points(neighbor_number);
1162 std::vector<Point3> points2(neighbor_number);
1163 int points_size = 0;
1169 it != search.end() && points_size < neighbor_number;
1171 points[points_size] = it->first;
1172 points2[points_size] = it->first;
1176 std::vector<Vector3> normals_vec(rotations);
1177 std::vector<float> normals_conf(rotations);
1179 for (
int i = 0; i < rotations; i++) {
1182 std::vector<Vector3> triplets(first, last);
1184 for (
unsigned int pt = 0; pt < points_size; pt++) {
1185 points[pt] = points2[pt].transform(
1186 rotMat[(n + i) % rotMat.size()]);
1188 normals_conf[i] = normal_at_point(d1, d2,
points, n,
1189 triplets, conf_interv);
1191 normals_vec[i] = nls[n].transform(
1192 rotMatInv[(n + i) % rotMat.size()]);
1194 nls[n] = normal_selection(rotations, normals_vec, normals_conf);
1196 #if defined(_OPENMP) && defined(USE_OPENMP_FOR_NORMEST)
1207 void points_radius(
float radius) {
1209 srand((
unsigned int)time(
NULL));
1211 nls.resize(pts.size());
1214 const int d1 = 2 * n_phi;
1215 const int d2 = n_phi + 1;
1218 std::vector<Matrix3> rotMat;
1219 std::vector<Matrix3> rotMatInv;
1220 generate_rotation_matrix(rotMat, rotMatInv, n_rot * 200);
1230 std::vector<float> conf_interv(n_planes);
1231 for (
int i = 0; i < n_planes; i++) {
1232 conf_interv[i] = 2.f / std::sqrt(i + 1.f);
1235 std::vector<int> vecInt;
1236 generate_random_int_vector(vecInt, 1000000);
1238 #if defined(_OPENMP) && defined(USE_OPENMP_FOR_NORMEST)
1239 #pragma omp parallel
1241 Tree tree(pts.begin(), pts.end());
1242 #pragma omp for schedule(guided)
1244 Tree tree(pts.begin(), pts.end());
1246 for (
int n = 0; n < (int)pts.size(); n++) {
1248 std::vector<Point3> points2;
1252 tree.search(std::back_inserter(points2), s_query);
1254 int points_size = (int)points2.size();
1256 if (points_size < lower_neighbor_bound_neighbors) {
1261 lower_neighbor_bound_neighbors);
1264 it != search.end() &&
1265 points_size < lower_neighbor_bound_neighbors;
1267 points2.push_back(it->first);
1270 points_size = points2.size();
1273 unsigned long int max_number_comb = points_size;
1274 max_number_comb *= points_size - 1;
1275 max_number_comb *= points_size - 2;
1276 if (max_number_comb < n_planes) {
1280 std::vector<Vector3> trip;
1282 if (rotations <= 1) {
1283 list_of_triplets(trip, points_size, n_planes, vecInt);
1285 list_of_triplets(trip, points_size, rotations * n_planes,
1289 std::vector<Vector3> normals_vec(rotations);
1290 std::vector<float> normals_conf(rotations);
1291 std::vector<Point3>
points(points_size);
1293 for (
int i = 0; i < rotations; i++) {
1296 std::vector<Vector3> triplets(first, last);
1298 for (
unsigned int pt = 0; pt < points_size; pt++) {
1299 points[pt] = points2[pt].transform(
1300 rotMat[(n + i) % rotMat.size()]);
1302 normals_conf[i] = normal_at_point(d1, d2,
points, n,
1303 triplets, conf_interv);
1305 normals_vec[i] = nls[n].transform(
1306 rotMatInv[(n + i) % rotMat.size()]);
1309 nls[n] = normal_selection(rotations, normals_vec, normals_conf);
1311 #if defined(_OPENMP) && defined(USE_OPENMP_FOR_NORMEST)
1322 void unif_knn(
int neighbor_number) {
1324 srand((
unsigned int)time(
NULL));
1326 nls.resize(pts.size());
1328 Tree tree(pts.begin(), pts.end());
1331 const int d1 = 2 * n_phi;
1332 const int d2 = n_phi + 1;
1335 std::vector<float> conf_interv(n_planes);
1336 for (
int i = 0; i < n_planes; i++) {
1337 conf_interv[i] = 2.f / std::sqrt(i + 1.f);
1341 std::vector<Matrix3> rotMat;
1342 std::vector<Matrix3> rotMatInv;
1343 generate_rotation_matrix(rotMat, rotMatInv, n_rot * 200);
1353 std::vector<Point3> points_rand;
1354 std::vector<int> vecInt;
1355 generate_random_points_vector(points_rand, 1000000);
1356 generate_random_int_vector(vecInt, 1000000);
1358 #if defined(_OPENMP) && defined(USE_OPENMP_FOR_NORMEST)
1359 #pragma omp parallel for schedule(guided)
1361 for (
int n = 0; n < (int)pts.size(); n++) {
1362 std::vector<Point3>
points(neighbor_number);
1363 int points_size = 0;
1365 #if defined(_OPENMP) && defined(USE_OPENMP_FOR_NORMEST)
1366 #pragma omp critical
1373 it != search.end() && points_size < neighbor_number;
1375 points[points_size] = it->first;
1377 if (radius < it->second) {
1378 radius = it->second;
1383 if (points_size != neighbor_number) {
1386 radius = sqrt(radius);
1388 float s_radius = radius / small_radius_factor;
1394 std::vector<Triplet> trip;
1395 generate_list_of_triplets(trip, rotations * n_planes, radius,
1396 s_radius, tree_neighbors, pts[n],
1397 points_rand, vecInt);
1399 std::vector<Vector3> normals_vec(rotations);
1400 std::vector<float> normals_conf(rotations);
1402 for (
int i = 0; i < rotations; i++) {
1405 std::vector<Triplet> triplets(first, last);
1407 for (
unsigned int tr = 0; tr < triplets.size(); tr++) {
1408 triplets[tr](0) = triplets[tr](0).transform(
1409 rotMat[(n + i) % rotMat.size()]);
1410 triplets[tr](1) = triplets[tr](1).transform(
1411 rotMat[(n + i) % rotMat.size()]);
1412 triplets[tr](2) = triplets[tr](2).transform(
1413 rotMat[(n + i) % rotMat.size()]);
1416 normals_conf[i] = normal_at_point(d1, d2, points_size, n,
1417 triplets, conf_interv);
1420 nls[n].transform(rotMatInv[(n + i) % rotMat.size()]);
1423 nls[n] = normal_selection(rotations, normals_vec, normals_conf);
1433 void unif_radius(
float radius) {
1435 srand((
unsigned int)time(
NULL));
1437 nls.resize(pts.size());
1439 Tree tree(pts.begin(), pts.end());
1442 const int d1 = 2 * n_phi;
1443 const int d2 = n_phi + 1;
1446 std::vector<float> conf_interv(n_planes);
1447 for (
int i = 0; i < n_planes; i++) {
1448 conf_interv[i] = 2.f / std::sqrt(i + 1.f);
1452 std::vector<Matrix3> rotMat;
1453 std::vector<Matrix3> rotMatInv;
1454 generate_rotation_matrix(rotMat, rotMatInv, n_rot * 200);
1464 std::vector<Point3> points_rand;
1465 std::vector<int> vecInt;
1466 generate_random_points_vector(points_rand, 1000000);
1467 generate_random_int_vector(vecInt, 1000000);
1469 #if defined(_OPENMP) && defined(USE_OPENMP_FOR_NORMEST)
1470 #pragma omp parallel for schedule(guided)
1472 for (
int n = 0; n < (int)pts.size(); n++) {
1473 std::vector<Point3>
points;
1475 #if defined(_OPENMP) && defined(USE_OPENMP_FOR_NORMEST)
1476 #pragma omp critical
1478 { tree.search(std::back_inserter(
points), s_query); }
1480 int points_size =
points.size();
1481 float radius2 = radius;
1483 if (points_size < lower_neighbor_bound_neighbors) {
1486 #if defined(_OPENMP) && defined(USE_OPENMP_FOR_NORMEST)
1487 #pragma omp critical
1492 lower_neighbor_bound_neighbors);
1495 it != search.end() &&
1496 points_size < lower_neighbor_bound_neighbors;
1498 points.push_back(it->first);
1500 if (radius2 < it->second) {
1501 radius2 = it->second;
1505 points_size =
points.size();
1508 float s_radius = radius2 / small_radius_factor;
1514 std::vector<Triplet> trip;
1515 generate_list_of_triplets(trip, rotations * n_planes, radius2,
1516 s_radius, tree_neighbors, pts[n],
1517 points_rand, vecInt);
1519 std::vector<Vector3> normals_vec(rotations);
1520 std::vector<float> normals_conf(rotations);
1522 for (
int i = 0; i < rotations; i++) {
1525 std::vector<Triplet> triplets(first, last);
1527 for (
unsigned int tr = 0; tr < triplets.size(); tr++) {
1528 triplets[tr](0) = triplets[tr](0).transform(
1529 rotMat[(n + i) % rotMat.size()]);
1530 triplets[tr](1) = triplets[tr](1).transform(
1531 rotMat[(n + i) % rotMat.size()]);
1532 triplets[tr](2) = triplets[tr](2).transform(
1533 rotMat[(n + i) % rotMat.size()]);
1536 normals_conf[i] = normal_at_point(d1, d2, points_size, n,
1537 triplets, conf_interv);
1540 nls[n].transform(rotMatInv[(n + i) % rotMat.size()]);
1542 nls[n] = normal_selection(rotations, normals_vec, normals_conf);
1552 void cubes_knn(
int neighbor_number) {
1554 nls.resize(pts.size());
1557 srand((
unsigned int)time(
NULL));
1560 const int d1 = 2 * n_phi;
1561 const int d2 = n_phi + 1;
1564 std::vector<float> conf_interv(n_planes);
1565 for (
int i = 0; i < n_planes; i++) {
1566 conf_interv[i] = 2.f / std::sqrt(i + 1.f);
1570 std::vector<Matrix3> rotMat;
1571 std::vector<Matrix3> rotMatInv;
1572 generate_rotation_matrix(rotMat, rotMatInv, n_rot * 200);
1582 std::vector<int> cubes_idx;
1583 std::vector<int> vecInt;
1584 generate_cube_vector(cubes_idx, 1000000);
1585 generate_random_int_vector(vecInt, 1000000);
1587 #if defined(_OPENMP) && defined(USE_OPENMP_FOR_NORMEST)
1588 #pragma omp parallel
1590 Tree tree(pts.begin(), pts.end());
1591 #pragma omp for schedule(guided)
1593 Tree tree(pts.begin(), pts.end());
1595 for (
int n = 0; n < (int)pts.size(); n++) {
1596 std::vector<Point3> points2(neighbor_number);
1597 std::vector<Point3>
points(neighbor_number);
1598 int points_size = 0;
1605 it != search.end() && points_size < neighbor_number;
1607 points2[points_size] = it->first;
1608 points[points_size] = it->first;
1610 if (radius < it->second) {
1611 radius = it->second;
1615 if (points_size != neighbor_number) {
1618 radius = sqrt(radius);
1620 std::vector<int> *cubes =
1621 new std::vector<int>[n_cubes * n_cubes * n_cubes];
1622 std::vector<Vector3> triplets;
1623 std::vector<Vector3> normals_vec(rotations);
1624 std::vector<float> normals_conf(rotations);
1626 for (
int i = 0; i < rotations; i++) {
1627 assign_points_to_cubes(cubes, radius, pts[n],
points,
1629 rotMat[(n + i) % rotMat.size()]);
1631 generate_cubes_triplets(triplets, cubes, cubes_idx, vecInt);
1634 normals_conf[i] = normal_at_point(d1, d2,
points, n,
1635 triplets, conf_interv);
1638 for (
unsigned int pt = 0; pt < points_size; pt++) {
1639 points[pt] = points2[pt];
1641 normals_vec[i] = nls[n].transform(
1642 rotMatInv[(n + i) % rotMat.size()]);
1645 nls[n] = normal_selection(rotations, normals_vec, normals_conf);
1649 #if defined(_OPENMP) && defined(USE_OPENMP_FOR_NORMEST)
1660 void cubes_radius(
float radius) {
1662 nls.resize(pts.size());
1665 srand((
unsigned int)time(
NULL));
1668 const int d1 = 2 * n_phi;
1669 const int d2 = n_phi + 1;
1672 std::vector<float> conf_interv(n_planes);
1673 for (
int i = 0; i < n_planes; i++) {
1674 conf_interv[i] = 2.f / std::sqrt(i + 1.f);
1678 std::vector<Matrix3> rotMat;
1679 std::vector<Matrix3> rotMatInv;
1680 generate_rotation_matrix(rotMat, rotMatInv, n_rot * 200);
1690 std::vector<int> cubes_idx;
1691 std::vector<int> vecInt;
1692 generate_cube_vector(cubes_idx, 1000000);
1693 generate_random_int_vector(vecInt, 1000000);
1695 #if defined(_OPENMP) && defined(USE_OPENMP_FOR_NORMEST)
1696 #pragma omp parallel
1698 Tree tree(pts.begin(), pts.end());
1699 #pragma omp for schedule(guided)
1701 Tree tree(pts.begin(), pts.end());
1703 for (
int n = 0; n < (int)pts.size(); n++) {
1704 std::vector<Point3> points2;
1706 tree.search(std::back_inserter(points2), s_query);
1708 int points_size = points2.size();
1709 float radius2 = radius;
1710 if (points_size < lower_neighbor_bound_neighbors) {
1715 lower_neighbor_bound_neighbors);
1718 it != search.end() &&
1719 points_size < lower_neighbor_bound_neighbors;
1721 points2.push_back(it->first);
1723 if (radius2 < it->second) {
1724 radius2 = it->second;
1727 points_size = points2.size();
1730 std::vector<int> *cubes =
1731 new std::vector<int>[n_cubes * n_cubes * n_cubes];
1732 std::vector<Vector3> triplets;
1733 std::vector<Vector3> normals_vec(rotations);
1734 std::vector<float> normals_conf(rotations);
1735 std::vector<Point3>
points(points_size);
1737 for (
int i = 0; i < rotations; i++) {
1738 assign_points_to_cubes(cubes, radius2, pts[n],
points,
1740 rotMat[(n + i) % rotMat.size()]);
1742 generate_cubes_triplets(triplets, cubes, cubes_idx, vecInt);
1745 normals_conf[i] = normal_at_point(d1, d2,
points, n,
1746 triplets, conf_interv);
1749 for (
unsigned int pt = 0; pt < points_size; pt++) {
1750 points[pt] = points2[pt];
1752 normals_vec[i] = nls[n].transform(
1753 rotMatInv[(n + i) % rotMat.size()]);
1756 nls[n] = normal_selection(rotations, normals_vec, normals_conf);
1760 #if defined(_OPENMP) && defined(USE_OPENMP_FOR_NORMEST)
simple class for triplet of points
My_Triplet(T a, T b, T c)
T operator()(int i) const
Class grouping different variant of the algorithm.
void estimate(int method=POINTS, int neighborhood_type=KNN, float neighborhood_size=200)
int & minimal_neighbor_number_for_range_search()
std::vector< Point3 >::iterator vecPt3Iterator
std::vector< Vector3 > normal_cloud() const
CGAL_Normal_Estimator(std::vector< Point3 > &points, std::vector< Vector3 > &normals)
Constructor.
CGAL::Vector_3< Kernel > Vector3
int & normal_selection_mode()
std::vector< Point3 > & point_cloud()
int minimal_neighbor_number_for_range_search() const
CGAL::Simple_cartesian< float > Kernel
float cluster_angle_rad() const
CGAL::Fuzzy_sphere< TreeTraits > Fuzzy_sphere
My_Triplet< Point3 > Triplet
int number_of_cubes() const
std::vector< Point3 > point_cloud() const
float small_radius_fact() const
CGAL::Orthogonal_k_neighbor_search< TreeTraits > Neighbor_search
std::vector< Triplet >::iterator vecTripIterator
std::vector< Vector3 > & normal_cloud()
int normal_selection_mode() const
CGAL::Search_traits_3< Kernel > TreeTraits
int rotation_number() const
CGAL::Kd_tree< TreeTraits > Tree
CGAL::Aff_transformation_3< Kernel > Matrix3
float & cluster_angle_rad()
int number_of_planes() const
float & small_radius_fact()
std::vector< Vector3 >::iterator vecVec3Iterator
Neighbor_search::iterator Neighbor_search_iterator
CGAL::Point_3< Kernel > Point3
QTextStream & endl(QTextStream &stream)
MiniVec< float, N > floor(const MiniVec< float, N > &a)