38 #ifndef PCL_SURFACE_IMPL_GP3_H_
39 #define PCL_SURFACE_IMPL_GP3_H_
41 #include <pcl/surface/gp3.h>
44 template <
typename Po
intInT>
void
48 output.
polygons.reserve (2 * indices_->size ());
49 if (!reconstructPolygons (output.
polygons))
51 PCL_ERROR (
"[pcl::%s::performReconstruction] Reconstruction failed. Check parameters: search radius (%f) or mu (%f) before continuing.\n", getClassName ().c_str (), search_radius_, mu_);
59 template <
typename Po
intInT>
void
63 polygons.reserve (2 * indices_->size ());
64 if (!reconstructPolygons (polygons))
66 PCL_ERROR (
"[pcl::%s::performReconstruction] Reconstruction failed. Check parameters: search radius (%f) or mu (%f) before continuing.\n", getClassName ().c_str (), search_radius_, mu_);
72 template <
typename Po
intInT>
bool
75 if (search_radius_ <= 0 || mu_ <= 0)
80 const double sqr_mu = mu_*mu_;
81 const double sqr_max_edge = search_radius_*search_radius_;
82 if (nnn_ >
static_cast<int> (indices_->size ()))
83 nnn_ =
static_cast<int> (indices_->size ());
87 std::vector<float> sqrDists (nnn_);
93 const Eigen::Vector2f uvn_nn_qp_zero = Eigen::Vector2f::Zero();
94 Eigen::Vector2f uvn_current;
95 Eigen::Vector2f uvn_prev;
96 Eigen::Vector2f uvn_next;
99 already_connected_ =
false;
107 part_.resize(indices_->size (), -1);
108 state_.resize(indices_->size (), FREE);
109 source_.resize(indices_->size (), NONE);
110 ffn_.resize(indices_->size (), NONE);
111 sfn_.resize(indices_->size (), NONE);
112 fringe_queue_.clear ();
116 if (!input_->is_dense)
119 for (
const auto& idx : (*indices_))
120 if (!std::isfinite ((*input_)[idx].x) ||
121 !std::isfinite ((*input_)[idx].y) ||
122 !std::isfinite ((*input_)[idx].z))
128 coords_.reserve (indices_->size ());
129 std::vector<int> point2index (input_->size (), -1);
130 for (
int cp = 0; cp < static_cast<int> (indices_->size ()); ++
cp)
132 coords_.push_back((*input_)[(*indices_)[
cp]].getVector3fMap());
133 point2index[(*indices_)[
cp]] =
cp;
137 int is_free=0, nr_parts=0, increase_nnn4fn=0, increase_nnn4s=0, increase_dist=0;
138 angles_.resize(nnn_);
139 std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > uvn_nn (nnn_);
140 Eigen::Vector2f uvn_s;
143 while (is_free != NONE)
146 if (state_[R_] == FREE)
149 part_[R_] = part_index++;
154 tree_->nearestKSearch (indices_->at (R_), nnn_, nnIdx, sqrDists);
155 double sqr_dist_threshold = (std::min)(sqr_max_edge, sqr_mu * sqrDists[1]);
158 for (
int i = 1; i < nnn_; i++)
162 nnIdx[i] = point2index[nnIdx[i]];
166 const Eigen::Vector3f nc = (*input_)[(*indices_)[R_]].getNormalVector3fMap ();
169 v_ = nc.unitOrthogonal ();
173 float dist = nc.dot (coords_[R_]);
174 proj_qp_ = coords_[R_] - dist * nc;
178 std::vector<doubleEdge> doubleEdges;
179 for (
int i = 1; i < nnn_; i++)
182 tmp_ = coords_[nnIdx[i]] - proj_qp_;
183 uvn_nn[i][0] = tmp_.dot(u_);
184 uvn_nn[i][1] = tmp_.dot(v_);
186 angles_[i].angle = std::atan2(uvn_nn[i][1], uvn_nn[i][0]);
188 angles_[i].index = nnIdx[i];
190 (state_[nnIdx[i]] == COMPLETED) || (state_[nnIdx[i]] == BOUNDARY)
191 || (state_[nnIdx[i]] == NONE) || (nnIdx[i] == UNAVAILABLE)
192 || (sqrDists[i] > sqr_dist_threshold)
194 angles_[i].visible =
false;
196 angles_[i].visible =
true;
198 if ((state_[nnIdx[i]] == FRINGE) || (state_[nnIdx[i]] == BOUNDARY))
203 tmp_ = coords_[ffn_[nnIdx[i]]] - proj_qp_;
204 e.first[0] = tmp_.dot(u_);
205 e.first[1] = tmp_.dot(v_);
206 tmp_ = coords_[sfn_[nnIdx[i]]] - proj_qp_;
207 e.second[0] = tmp_.dot(u_);
208 e.second[1] = tmp_.dot(v_);
209 doubleEdges.push_back(e);
212 angles_[0].visible =
false;
215 for (
int i = 1; i < nnn_; i++)
216 if ((angles_[i].visible) && (ffn_[R_] != nnIdx[i]) && (sfn_[R_] != nnIdx[i]))
218 bool visibility =
true;
219 for (
int j = 0; j < nr_edge; j++)
221 if (ffn_[nnIdx[doubleEdges[j].index]] != nnIdx[i])
222 visibility =
isVisible(uvn_nn[i], uvn_nn[doubleEdges[j].index], doubleEdges[j].first, Eigen::Vector2f::Zero());
225 if (sfn_[nnIdx[doubleEdges[j].index]] != nnIdx[i])
226 visibility =
isVisible(uvn_nn[i], uvn_nn[doubleEdges[j].index], doubleEdges[j].second, Eigen::Vector2f::Zero());
230 angles_[i].visible = visibility;
234 bool not_found =
true;
238 while ((left < nnn_) && ((!angles_[left].visible) || (state_[nnIdx[left]] > FREE))) left++;
244 while ((right < nnn_) && ((!angles_[right].visible) || (state_[nnIdx[right]] > FREE))) right++;
247 if ((coords_[nnIdx[left]] - coords_[nnIdx[right]]).squaredNorm () > sqr_max_edge)
251 addFringePoint (nnIdx[right], R_);
252 addFringePoint (nnIdx[left], nnIdx[right]);
253 addFringePoint (R_, nnIdx[left]);
254 state_[R_] = state_[nnIdx[left]] = state_[nnIdx[right]] = FRINGE;
255 ffn_[R_] = nnIdx[left];
256 sfn_[R_] = nnIdx[right];
257 ffn_[nnIdx[left]] = nnIdx[right];
258 sfn_[nnIdx[left]] = R_;
259 ffn_[nnIdx[right]] = R_;
260 sfn_[nnIdx[right]] = nnIdx[left];
261 addTriangle (R_, nnIdx[left], nnIdx[right], polygons);
274 for (std::size_t temp = 0; temp < indices_->size (); temp++)
276 if (state_[temp] == FREE)
283 bool is_fringe =
true;
288 int fqSize =
static_cast<int> (fringe_queue_.size ());
289 while ((fqIdx < fqSize) && (state_[fringe_queue_[fqIdx]] != FRINGE))
298 R_ = fringe_queue_[fqIdx];
301 if (ffn_[R_] == sfn_[R_])
303 state_[R_] = COMPLETED;
308 tree_->nearestKSearch (indices_->at (R_), nnn_, nnIdx, sqrDists);
311 for (
int i = 1; i < nnn_; i++)
315 nnIdx[i] = point2index[nnIdx[i]];
319 double sqr_source_dist = (coords_[R_] - coords_[source_[R_]]).squaredNorm ();
320 double sqr_ffn_dist = (coords_[R_] - coords_[ffn_[R_]]).squaredNorm ();
321 double sqr_sfn_dist = (coords_[R_] - coords_[sfn_[R_]]).squaredNorm ();
322 double max_sqr_fn_dist = (std::max)(sqr_ffn_dist, sqr_sfn_dist);
323 double sqr_dist_threshold = (std::min)(sqr_max_edge, sqr_mu * sqrDists[1]);
324 if (max_sqr_fn_dist > sqrDists[nnn_-1])
326 if (0 == increase_nnn4fn)
327 PCL_WARN(
"Not enough neighbors are considered: ffn or sfn out of range! Consider increasing nnn_... Setting R=%d to be BOUNDARY!\n", R_);
329 state_[R_] = BOUNDARY;
332 double max_sqr_fns_dist = (std::max)(sqr_source_dist, max_sqr_fn_dist);
333 if (max_sqr_fns_dist > sqrDists[nnn_-1])
335 if (0 == increase_nnn4s)
336 PCL_WARN(
"Not enough neighbors are considered: source of R=%d is out of range! Consider increasing nnn_...\n", R_);
341 const Eigen::Vector3f nc = (*input_)[(*indices_)[R_]].getNormalVector3fMap ();
344 v_ = nc.unitOrthogonal ();
348 float dist = nc.dot (coords_[R_]);
349 proj_qp_ = coords_[R_] - dist * nc;
353 std::vector<doubleEdge> doubleEdges;
354 for (
int i = 1; i < nnn_; i++)
356 tmp_ = coords_[nnIdx[i]] - proj_qp_;
357 uvn_nn[i][0] = tmp_.dot(u_);
358 uvn_nn[i][1] = tmp_.dot(v_);
361 angles_[i].angle = std::atan2(uvn_nn[i][1], uvn_nn[i][0]);
363 angles_[i].index = nnIdx[i];
364 angles_[i].nnIndex = i;
366 (state_[nnIdx[i]] == COMPLETED) || (state_[nnIdx[i]] == BOUNDARY)
367 || (state_[nnIdx[i]] == NONE) || (nnIdx[i] == UNAVAILABLE)
368 || (sqrDists[i] > sqr_dist_threshold)
370 angles_[i].visible =
false;
372 angles_[i].visible =
true;
373 if ((ffn_[R_] == nnIdx[i]) || (sfn_[R_] == nnIdx[i]))
374 angles_[i].visible =
true;
375 bool same_side =
true;
376 const Eigen::Vector3f neighbor_normal = (*input_)[(*indices_)[nnIdx[i]]].getNormalVector3fMap ();
377 double cosine = nc.dot (neighbor_normal);
378 if (cosine > 1) cosine = 1;
379 if (cosine < -1) cosine = -1;
380 double angle = std::acos (cosine);
381 if ((!consistent_) && (angle >
M_PI/2))
382 angle =
M_PI - angle;
383 if (angle > eps_angle_)
385 angles_[i].visible =
false;
389 if ((i!=0) && (same_side) && ((state_[nnIdx[i]] == FRINGE) || (state_[nnIdx[i]] == BOUNDARY)))
394 tmp_ = coords_[ffn_[nnIdx[i]]] - proj_qp_;
395 e.first[0] = tmp_.dot(u_);
396 e.first[1] = tmp_.dot(v_);
397 tmp_ = coords_[sfn_[nnIdx[i]]] - proj_qp_;
398 e.second[0] = tmp_.dot(u_);
399 e.second[1] = tmp_.dot(v_);
400 doubleEdges.push_back(e);
402 if ((state_[nnIdx[i]] == FRINGE) && (ffn_[R_] != nnIdx[i]) && (sfn_[R_] != nnIdx[i]))
404 double angle1 = std::atan2(e.first[1] - uvn_nn[i][1], e.first[0] - uvn_nn[i][0]);
405 double angle2 = std::atan2(e.second[1] - uvn_nn[i][1], e.second[0] - uvn_nn[i][0]);
406 double angleMin, angleMax;
417 double angleR = angles_[i].angle +
M_PI;
420 if ((source_[nnIdx[i]] == ffn_[nnIdx[i]]) || (source_[nnIdx[i]] == sfn_[nnIdx[i]]))
422 if ((angleMax - angleMin) <
M_PI)
424 if ((angleMin < angleR) && (angleR < angleMax))
425 angles_[i].visible =
false;
429 if ((angleR < angleMin) || (angleMax < angleR))
430 angles_[i].visible =
false;
435 tmp_ = coords_[source_[nnIdx[i]]] - proj_qp_;
436 uvn_s[0] = tmp_.dot(u_);
437 uvn_s[1] = tmp_.dot(v_);
438 double angleS = std::atan2(uvn_s[1] - uvn_nn[i][1], uvn_s[0] - uvn_nn[i][0]);
439 if ((angleMin < angleS) && (angleS < angleMax))
441 if ((angleMin < angleR) && (angleR < angleMax))
442 angles_[i].visible =
false;
446 if ((angleR < angleMin) || (angleMax < angleR))
447 angles_[i].visible =
false;
453 angles_[0].visible =
false;
456 for (
int i = 1; i < nnn_; i++)
457 if ((angles_[i].visible) && (ffn_[R_] != nnIdx[i]) && (sfn_[R_] != nnIdx[i]))
459 bool visibility =
true;
460 for (
int j = 0; j < nr_edge; j++)
462 if (doubleEdges[j].index != i)
464 const auto& f = ffn_[nnIdx[doubleEdges[j].index]];
465 if ((f != nnIdx[i]) && (f != R_))
466 visibility =
isVisible(uvn_nn[i], uvn_nn[doubleEdges[j].index], doubleEdges[j].first, Eigen::Vector2f::Zero());
470 const auto& s = sfn_[nnIdx[doubleEdges[j].index]];
471 if ((s != nnIdx[i]) && (s != R_))
472 visibility =
isVisible(uvn_nn[i], uvn_nn[doubleEdges[j].index], doubleEdges[j].second, Eigen::Vector2f::Zero());
477 angles_[i].visible = visibility;
481 std::sort (angles_.begin (), angles_.end (), GreedyProjectionTriangulation<PointInT>::nnAngleSortAsc);
484 if (angles_[2].visible ==
false)
486 if ( !( (angles_[0].index == ffn_[R_] && angles_[1].index == sfn_[R_]) || (angles_[0].index == sfn_[R_] && angles_[1].index == ffn_[R_]) ) )
488 state_[R_] = BOUNDARY;
492 if ((source_[R_] == angles_[0].index) || (source_[R_] == angles_[1].index))
493 state_[R_] = BOUNDARY;
496 if (sqr_max_edge < (coords_[ffn_[R_]] - coords_[sfn_[R_]]).squaredNorm ())
498 state_[R_] = BOUNDARY;
502 tmp_ = coords_[source_[R_]] - proj_qp_;
503 uvn_s[0] = tmp_.dot(u_);
504 uvn_s[1] = tmp_.dot(v_);
505 double angleS = std::atan2(uvn_s[1], uvn_s[0]);
506 double dif = angles_[1].angle - angles_[0].angle;
507 if ((angles_[0].angle < angleS) && (angleS < angles_[1].angle))
509 if (dif < 2*
M_PI - maximum_angle_)
510 state_[R_] = BOUNDARY;
512 closeTriangle (polygons);
516 if (dif >= maximum_angle_)
517 state_[R_] = BOUNDARY;
519 closeTriangle (polygons);
528 int start = -1, end = -1;
529 for (
int i=0; i<nnn_; i++)
531 if (ffn_[R_] == angles_[i].index)
534 if (sfn_[R_] == angles_[i+1].index)
539 for (i = i+2; i < nnn_; i++)
540 if (sfn_[R_] == angles_[i].index)
546 for (i = i+2; i < nnn_; i++)
547 if (sfn_[R_] == angles_[i].index)
553 if (sfn_[R_] == angles_[i].index)
556 if (ffn_[R_] == angles_[i+1].index)
561 for (i = i+2; i < nnn_; i++)
562 if (ffn_[R_] == angles_[i].index)
568 for (i = i+2; i < nnn_; i++)
569 if (ffn_[R_] == angles_[i].index)
578 if ((start < 0) || (end < 0) || (end == nnn_) || (!angles_[start].visible) || (!angles_[end].visible))
580 state_[R_] = BOUNDARY;
585 int last_visible = end;
586 while ((last_visible+1<nnn_) && (angles_[last_visible+1].visible)) last_visible++;
589 bool need_invert =
false;
590 if ((source_[R_] == ffn_[R_]) || (source_[R_] == sfn_[R_]))
592 if ((angles_[end].angle - angles_[start].angle) <
M_PI)
598 for (sourceIdx=0; sourceIdx<nnn_; sourceIdx++)
599 if (angles_[sourceIdx].index == source_[R_])
601 if (sourceIdx == nnn_)
603 int vis_free = NONE, nnCB = NONE;
604 for (
int i = 1; i < nnn_; i++)
607 if ((state_[nnIdx[i]] == COMPLETED) || (state_[nnIdx[i]] == BOUNDARY))
612 if (vis_free != NONE)
617 if (state_[angles_[i].index] <= FREE)
619 if (i <= last_visible)
630 while (angles_[nCB].index != nnIdx[nnCB]) nCB++;
634 if (vis_free != NONE)
636 if ((vis_free < start) || (vis_free > end))
643 if ((nCB == start) || (nCB == end))
645 bool inside_CB =
false;
646 bool outside_CB =
false;
647 for (
int i=0; i<nnn_; i++)
650 ((state_[angles_[i].index] == COMPLETED) || (state_[angles_[i].index] == BOUNDARY))
651 && (i != start) && (i != end)
654 if ((angles_[start].angle <= angles_[i].angle) && (angles_[i].angle <= angles_[end].angle))
668 if (inside_CB && !outside_CB)
670 else if (inside_CB || !outside_CB)
672 if ((angles_[end].angle - angles_[start].angle) <
M_PI)
678 if ((angles_[nCB].angle > angles_[start].angle) && (angles_[nCB].angle < angles_[end].angle))
689 else if ((angles_[start].angle < angles_[sourceIdx].angle) && (angles_[sourceIdx].angle < angles_[end].angle))
703 bool is_boundary =
false, is_skinny =
false;
704 std::vector<bool> gaps (nnn_,
false);
705 std::vector<bool> skinny (nnn_,
false);
706 std::vector<double> dif (nnn_);
707 std::vector<int> angleIdx; angleIdx.reserve (nnn_);
710 for (
int j=start; j<last_visible; j++)
712 dif[j] = (angles_[j+1].angle - angles_[j].angle);
713 if (dif[j] < minimum_angle_)
715 skinny[j] = is_skinny =
true;
717 else if (maximum_angle_ <= dif[j])
719 gaps[j] = is_boundary =
true;
721 if ((!gaps[j]) && (sqr_max_edge < (coords_[angles_[j+1].index] - coords_[angles_[j].index]).squaredNorm ()))
723 gaps[j] = is_boundary =
true;
725 angleIdx.push_back(j);
728 dif[last_visible] = (2*
M_PI + angles_[0].angle - angles_[last_visible].angle);
729 if (dif[last_visible] < minimum_angle_)
731 skinny[last_visible] = is_skinny =
true;
733 else if (maximum_angle_ <= dif[last_visible])
735 gaps[last_visible] = is_boundary =
true;
737 if ((!gaps[last_visible]) && (sqr_max_edge < (coords_[angles_[0].index] - coords_[angles_[last_visible].index]).squaredNorm ()))
739 gaps[last_visible] = is_boundary =
true;
741 angleIdx.push_back(last_visible);
743 for (
int j=0; j<end; j++)
745 dif[j] = (angles_[j+1].angle - angles_[j].angle);
746 if (dif[j] < minimum_angle_)
748 skinny[j] = is_skinny =
true;
750 else if (maximum_angle_ <= dif[j])
752 gaps[j] = is_boundary =
true;
754 if ((!gaps[j]) && (sqr_max_edge < (coords_[angles_[j+1].index] - coords_[angles_[j].index]).squaredNorm ()))
756 gaps[j] = is_boundary =
true;
758 angleIdx.push_back(j);
760 angleIdx.push_back(end);
765 for (
int j=start; j<end; j++)
767 dif[j] = (angles_[j+1].angle - angles_[j].angle);
768 if (dif[j] < minimum_angle_)
770 skinny[j] = is_skinny =
true;
772 else if (maximum_angle_ <= dif[j])
774 gaps[j] = is_boundary =
true;
776 if ((!gaps[j]) && (sqr_max_edge < (coords_[angles_[j+1].index] - coords_[angles_[j].index]).squaredNorm ()))
778 gaps[j] = is_boundary =
true;
780 angleIdx.push_back(j);
782 angleIdx.push_back(end);
786 state_[R_] = is_boundary ? BOUNDARY : COMPLETED;
788 auto first_gap_after = angleIdx.end ();
789 auto last_gap_before = angleIdx.begin ();
791 for (
auto it = angleIdx.begin (); it != angleIdx.end () - 1; ++it)
796 if (first_gap_after == angleIdx.end())
797 first_gap_after = it;
798 last_gap_before = it+1;
803 angleIdx.erase(first_gap_after+1, last_gap_before);
809 double angle_so_far = 0, angle_would_be;
810 double max_combined_angle = (std::min)(maximum_angle_,
M_PI-2*minimum_angle_);
814 std::vector<int> to_erase;
815 for (
auto it = angleIdx.begin()+1; it != angleIdx.end()-1; ++it)
820 angle_so_far += dif[*(it-1)];
822 angle_would_be = angle_so_far;
824 angle_would_be = angle_so_far + dif[*it];
826 (skinny[*it] || skinny[*(it-1)]) &&
827 ((state_[angles_[*it].index] <= FREE) || (state_[angles_[*(it-1)].index] <= FREE)) &&
828 ((!gaps[*it]) || (angles_[*it].nnIndex > angles_[*(it-1)].nnIndex)) &&
829 ((!gaps[*(it-1)]) || (angles_[*it].nnIndex > angles_[*(it+1)].nnIndex)) &&
830 (angle_would_be < max_combined_angle)
836 to_erase.push_back(*it);
840 gaps[*(it-1)] =
true;
841 to_erase.push_back(*it);
845 std::vector<int>::iterator prev_it;
846 int erased_idx =
static_cast<int> (to_erase.size ()) -1;
847 for (prev_it = it-1; (erased_idx != -1) && (it != angleIdx.begin()); --it)
848 if (*it == to_erase[erased_idx])
852 bool can_delete =
true;
853 for (
auto curr_it = prev_it+1; curr_it != it+1; ++curr_it)
855 tmp_ = coords_[angles_[*curr_it].index] - proj_qp_;
858 tmp_ = coords_[angles_[*prev_it].index] - proj_qp_;
859 S1[0] = tmp_.dot(u_);
860 S1[1] = tmp_.dot(v_);
861 tmp_ = coords_[angles_[*(it+1)].index] - proj_qp_;
862 S2[0] = tmp_.dot(u_);
863 S2[1] = tmp_.dot(v_);
874 to_erase.push_back(*it);
881 for (
const auto &idx : to_erase)
883 for (
auto iter = angleIdx.begin(); iter != angleIdx.end(); ++iter)
886 angleIdx.erase(iter);
893 changed_1st_fn_ =
false;
894 changed_2nd_fn_ =
false;
895 new2boundary_ = NONE;
896 for (
auto it = angleIdx.begin()+1; it != angleIdx.end()-1; ++it)
898 current_index_ = angles_[*it].index;
900 is_current_free_ =
false;
901 if (state_[current_index_] <= FREE)
903 state_[current_index_] = FRINGE;
904 is_current_free_ =
true;
906 else if (!already_connected_)
908 prev_is_ffn_ = (ffn_[current_index_] == angles_[*(it-1)].index) && (!gaps[*(it-1)]);
909 prev_is_sfn_ = (sfn_[current_index_] == angles_[*(it-1)].index) && (!gaps[*(it-1)]);
910 next_is_ffn_ = (ffn_[current_index_] == angles_[*(it+1)].index) && (!gaps[*it]);
911 next_is_sfn_ = (sfn_[current_index_] == angles_[*(it+1)].index) && (!gaps[*it]);
917 if (is_current_free_)
918 state_[current_index_] = NONE;
923 addTriangle (current_index_, angles_[*(it-1)].index, R_, polygons);
924 addFringePoint (current_index_, R_);
925 new2boundary_ = current_index_;
926 if (!already_connected_)
927 connectPoint (polygons, angles_[*(it-1)].index, R_,
928 angles_[*(it+1)].index,
929 uvn_nn[angles_[*it].nnIndex], uvn_nn[angles_[*(it-1)].nnIndex], uvn_nn_qp_zero);
930 else already_connected_ =
false;
931 if (ffn_[R_] == angles_[*(angleIdx.begin())].index)
933 ffn_[R_] = new2boundary_;
935 else if (sfn_[R_] == angles_[*(angleIdx.begin())].index)
937 sfn_[R_] = new2boundary_;
944 addFringePoint (current_index_, R_);
945 new2boundary_ = current_index_;
946 if (!already_connected_) connectPoint (polygons, R_, angles_[*(it+1)].index,
947 (it+2) == angleIdx.end() ? -1 : angles_[*(it+2)].index,
948 uvn_nn[angles_[*it].nnIndex], uvn_nn_qp_zero,
949 uvn_nn[angles_[*(it+1)].nnIndex]);
950 else already_connected_ =
false;
951 if (ffn_[R_] == angles_[*(angleIdx.end()-1)].index)
953 ffn_[R_] = new2boundary_;
955 else if (sfn_[R_] == angles_[*(angleIdx.end()-1)].index)
957 sfn_[R_] = new2boundary_;
963 addTriangle (current_index_, angles_[*(it-1)].index, R_, polygons);
964 addFringePoint (current_index_, R_);
965 if (!already_connected_) connectPoint (polygons, angles_[*(it-1)].index, angles_[*(it+1)].index,
966 (it+2) == angleIdx.end() ? -1 : gaps[*(it+1)] ? R_ : angles_[*(it+2)].index,
967 uvn_nn[angles_[*it].nnIndex],
968 uvn_nn[angles_[*(it-1)].nnIndex],
969 uvn_nn[angles_[*(it+1)].nnIndex]);
970 else already_connected_ =
false;
975 if (ffn_[R_] == sfn_[R_])
977 state_[R_] = COMPLETED;
979 if (!gaps[*(angleIdx.end()-2)])
981 addTriangle (angles_[*(angleIdx.end()-2)].index, angles_[*(angleIdx.end()-1)].index, R_, polygons);
982 addFringePoint (angles_[*(angleIdx.end()-2)].index, R_);
983 if (R_ == ffn_[angles_[*(angleIdx.end()-1)].index])
985 if (angles_[*(angleIdx.end()-2)].index == sfn_[angles_[*(angleIdx.end()-1)].index])
987 state_[angles_[*(angleIdx.end()-1)].index] = COMPLETED;
991 ffn_[angles_[*(angleIdx.end()-1)].index] = angles_[*(angleIdx.end()-2)].index;
994 else if (R_ == sfn_[angles_[*(angleIdx.end()-1)].index])
996 if (angles_[*(angleIdx.end()-2)].index == ffn_[angles_[*(angleIdx.end()-1)].index])
998 state_[angles_[*(angleIdx.end()-1)].index] = COMPLETED;
1002 sfn_[angles_[*(angleIdx.end()-1)].index] = angles_[*(angleIdx.end()-2)].index;
1006 if (!gaps[*(angleIdx.begin())])
1008 if (R_ == ffn_[angles_[*(angleIdx.begin())].index])
1010 if (angles_[*(angleIdx.begin()+1)].index == sfn_[angles_[*(angleIdx.begin())].index])
1012 state_[angles_[*(angleIdx.begin())].index] = COMPLETED;
1016 ffn_[angles_[*(angleIdx.begin())].index] = angles_[*(angleIdx.begin()+1)].index;
1019 else if (R_ == sfn_[angles_[*(angleIdx.begin())].index])
1021 if (angles_[*(angleIdx.begin()+1)].index == ffn_[angles_[*(angleIdx.begin())].index])
1023 state_[angles_[*(angleIdx.begin())].index] = COMPLETED;
1027 sfn_[angles_[*(angleIdx.begin())].index] = angles_[*(angleIdx.begin()+1)].index;
1033 PCL_DEBUG (
"Number of triangles: %lu\n", polygons.size());
1034 PCL_DEBUG (
"Number of unconnected parts: %d\n", nr_parts);
1035 if (increase_nnn4fn > 0)
1036 PCL_WARN (
"Number of neighborhood size increase requests for fringe neighbors: %d\n", increase_nnn4fn);
1037 if (increase_nnn4s > 0)
1038 PCL_WARN (
"Number of neighborhood size increase requests for source: %d\n", increase_nnn4s);
1039 if (increase_dist > 0)
1040 PCL_WARN (
"Number of automatic maximum distance increases: %d\n", increase_dist);
1043 std::sort (fringe_queue_.begin (), fringe_queue_.end ());
1044 fringe_queue_.erase (std::unique (fringe_queue_.begin (), fringe_queue_.end ()), fringe_queue_.end ());
1045 PCL_DEBUG (
"Number of processed points: %lu / %lu\n", fringe_queue_.size(), indices_->size ());
1050 template <
typename Po
intInT>
void
1053 state_[R_] = COMPLETED;
1054 addTriangle (angles_[0].index, angles_[1].index, R_, polygons);
1055 for (
int aIdx=0; aIdx<2; aIdx++)
1057 if (ffn_[angles_[aIdx].index] == R_)
1059 if (sfn_[angles_[aIdx].index] == angles_[(aIdx+1)%2].index)
1061 state_[angles_[aIdx].index] = COMPLETED;
1065 ffn_[angles_[aIdx].index] = angles_[(aIdx+1)%2].index;
1068 else if (sfn_[angles_[aIdx].index] == R_)
1070 if (ffn_[angles_[aIdx].index] == angles_[(aIdx+1)%2].index)
1072 state_[angles_[aIdx].index] = COMPLETED;
1076 sfn_[angles_[aIdx].index] = angles_[(aIdx+1)%2].index;
1083 template <
typename Po
intInT>
void
1085 std::vector<pcl::Vertices> &polygons,
1087 const Eigen::Vector2f &uvn_current,
1088 const Eigen::Vector2f &uvn_prev,
1089 const Eigen::Vector2f &uvn_next)
1091 if (is_current_free_)
1093 ffn_[current_index_] = prev_index;
1094 sfn_[current_index_] = next_index;
1098 if ((prev_is_ffn_ && next_is_sfn_) || (prev_is_sfn_ && next_is_ffn_))
1099 state_[current_index_] = COMPLETED;
1100 else if (prev_is_ffn_ && !next_is_sfn_)
1101 ffn_[current_index_] = next_index;
1102 else if (next_is_ffn_ && !prev_is_sfn_)
1103 ffn_[current_index_] = prev_index;
1104 else if (prev_is_sfn_ && !next_is_ffn_)
1105 sfn_[current_index_] = next_index;
1106 else if (next_is_sfn_ && !prev_is_ffn_)
1107 sfn_[current_index_] = prev_index;
1110 bool found_triangle =
false;
1111 if ((prev_index != R_) && ((ffn_[current_index_] == ffn_[prev_index]) || (ffn_[current_index_] == sfn_[prev_index])))
1113 found_triangle =
true;
1114 addTriangle (current_index_, ffn_[current_index_], prev_index, polygons);
1115 state_[prev_index] = COMPLETED;
1116 state_[ffn_[current_index_]] = COMPLETED;
1117 ffn_[current_index_] = next_index;
1119 else if ((prev_index != R_) && ((sfn_[current_index_] == ffn_[prev_index]) || (sfn_[current_index_] == sfn_[prev_index])))
1121 found_triangle =
true;
1122 addTriangle (current_index_, sfn_[current_index_], prev_index, polygons);
1123 state_[prev_index] = COMPLETED;
1124 state_[sfn_[current_index_]] = COMPLETED;
1125 sfn_[current_index_] = next_index;
1127 else if (state_[next_index] > FREE)
1129 if ((ffn_[current_index_] == ffn_[next_index]) || (ffn_[current_index_] == sfn_[next_index]))
1131 found_triangle =
true;
1132 addTriangle (current_index_, ffn_[current_index_], next_index, polygons);
1134 if (ffn_[current_index_] == ffn_[next_index])
1136 ffn_[next_index] = current_index_;
1140 sfn_[next_index] = current_index_;
1142 state_[ffn_[current_index_]] = COMPLETED;
1143 ffn_[current_index_] = prev_index;
1145 else if ((sfn_[current_index_] == ffn_[next_index]) || (sfn_[current_index_] == sfn_[next_index]))
1147 found_triangle =
true;
1148 addTriangle (current_index_, sfn_[current_index_], next_index, polygons);
1150 if (sfn_[current_index_] == ffn_[next_index])
1152 ffn_[next_index] = current_index_;
1156 sfn_[next_index] = current_index_;
1158 state_[sfn_[current_index_]] = COMPLETED;
1159 sfn_[current_index_] = prev_index;
1168 tmp_ = coords_[ffn_[current_index_]] - proj_qp_;
1169 uvn_ffn_[0] = tmp_.dot(u_);
1170 uvn_ffn_[1] = tmp_.dot(v_);
1171 tmp_ = coords_[sfn_[current_index_]] - proj_qp_;
1172 uvn_sfn_[0] = tmp_.dot(u_);
1173 uvn_sfn_[1] = tmp_.dot(v_);
1174 bool prev_ffn =
isVisible(uvn_prev, uvn_next, uvn_current, uvn_ffn_) &&
isVisible(uvn_prev, uvn_sfn_, uvn_current, uvn_ffn_);
1175 bool prev_sfn =
isVisible(uvn_prev, uvn_next, uvn_current, uvn_sfn_) &&
isVisible(uvn_prev, uvn_ffn_, uvn_current, uvn_sfn_);
1176 bool next_ffn =
isVisible(uvn_next, uvn_prev, uvn_current, uvn_ffn_) &&
isVisible(uvn_next, uvn_sfn_, uvn_current, uvn_ffn_);
1177 bool next_sfn =
isVisible(uvn_next, uvn_prev, uvn_current, uvn_sfn_) &&
isVisible(uvn_next, uvn_ffn_, uvn_current, uvn_sfn_);
1179 if (prev_ffn && next_sfn && prev_sfn && next_ffn)
1182 double prev2f = (coords_[ffn_[current_index_]] - coords_[prev_index]).squaredNorm ();
1183 double next2s = (coords_[sfn_[current_index_]] - coords_[next_index]).squaredNorm ();
1184 double prev2s = (coords_[sfn_[current_index_]] - coords_[prev_index]).squaredNorm ();
1185 double next2f = (coords_[ffn_[current_index_]] - coords_[next_index]).squaredNorm ();
1186 if (prev2f < prev2s)
1188 if (prev2f < next2f)
1190 if (prev2f < next2s)
1197 if (next2f < next2s)
1205 if (prev2s < next2f)
1207 if (prev2s < next2s)
1214 if (next2f < next2s)
1221 else if (prev_ffn && next_sfn)
1224 double prev2f = (coords_[ffn_[current_index_]] - coords_[prev_index]).squaredNorm ();
1225 double next2s = (coords_[sfn_[current_index_]] - coords_[next_index]).squaredNorm ();
1226 if (prev2f < next2s)
1231 else if (prev_sfn && next_ffn)
1234 double prev2s = (coords_[sfn_[current_index_]] - coords_[prev_index]).squaredNorm ();
1235 double next2f = (coords_[ffn_[current_index_]] - coords_[next_index]).squaredNorm ();
1236 if (prev2s < next2f)
1242 else if (prev_ffn && !next_sfn && !prev_sfn && !next_ffn)
1244 else if (!prev_ffn && !next_sfn && prev_sfn && !next_ffn)
1246 else if (!prev_ffn && !next_sfn && !prev_sfn && next_ffn)
1248 else if (!prev_ffn && next_sfn && !prev_sfn && !next_ffn)
1253 double prev2f = (coords_[ffn_[current_index_]] - coords_[prev_index]).squaredNorm ();
1256 double prev2s = (coords_[sfn_[current_index_]] - coords_[prev_index]).squaredNorm ();
1257 if (prev2s < prev2f)
1264 double next2f = (coords_[ffn_[current_index_]] - coords_[next_index]).squaredNorm ();
1265 if (next2f < prev2f)
1273 double next2s = (coords_[sfn_[current_index_]] - coords_[next_index]).squaredNorm ();
1276 double prev2s = (coords_[sfn_[current_index_]] - coords_[prev_index]).squaredNorm ();
1277 if (prev2s < next2s)
1284 double next2f = (coords_[ffn_[current_index_]] - coords_[next_index]).squaredNorm ();
1285 if (next2f < next2s)
1295 addTriangle (current_index_, ffn_[current_index_], prev_index, polygons);
1298 if (ffn_[prev_index] == current_index_)
1300 ffn_[prev_index] = ffn_[current_index_];
1302 else if (sfn_[prev_index] == current_index_)
1304 sfn_[prev_index] = ffn_[current_index_];
1306 else if (ffn_[prev_index] == R_)
1308 changed_1st_fn_ =
true;
1309 ffn_[prev_index] = ffn_[current_index_];
1311 else if (sfn_[prev_index] == R_)
1313 changed_1st_fn_ =
true;
1314 sfn_[prev_index] = ffn_[current_index_];
1316 else if (prev_index == R_)
1318 new2boundary_ = ffn_[current_index_];
1322 if (ffn_[ffn_[current_index_]] == current_index_)
1324 ffn_[ffn_[current_index_]] = prev_index;
1326 else if (sfn_[ffn_[current_index_]] == current_index_)
1328 sfn_[ffn_[current_index_]] = prev_index;
1332 ffn_[current_index_] = next_index;
1338 addTriangle (current_index_, sfn_[current_index_], prev_index, polygons);
1341 if (ffn_[prev_index] == current_index_)
1343 ffn_[prev_index] = sfn_[current_index_];
1345 else if (sfn_[prev_index] == current_index_)
1347 sfn_[prev_index] = sfn_[current_index_];
1349 else if (ffn_[prev_index] == R_)
1351 changed_1st_fn_ =
true;
1352 ffn_[prev_index] = sfn_[current_index_];
1354 else if (sfn_[prev_index] == R_)
1356 changed_1st_fn_ =
true;
1357 sfn_[prev_index] = sfn_[current_index_];
1359 else if (prev_index == R_)
1361 new2boundary_ = sfn_[current_index_];
1365 if (ffn_[sfn_[current_index_]] == current_index_)
1367 ffn_[sfn_[current_index_]] = prev_index;
1369 else if (sfn_[sfn_[current_index_]] == current_index_)
1371 sfn_[sfn_[current_index_]] = prev_index;
1375 sfn_[current_index_] = next_index;
1381 addTriangle (current_index_, ffn_[current_index_], next_index, polygons);
1382 auto neighbor_update = next_index;
1385 if (state_[next_index] <= FREE)
1387 state_[next_index] = FRINGE;
1388 ffn_[next_index] = current_index_;
1389 sfn_[next_index] = ffn_[current_index_];
1393 if (ffn_[next_index] == R_)
1395 changed_2nd_fn_ =
true;
1396 ffn_[next_index] = ffn_[current_index_];
1398 else if (sfn_[next_index] == R_)
1400 changed_2nd_fn_ =
true;
1401 sfn_[next_index] = ffn_[current_index_];
1403 else if (next_index == R_)
1405 new2boundary_ = ffn_[current_index_];
1406 if (next_next_index == new2boundary_)
1407 already_connected_ =
true;
1409 else if (ffn_[next_index] == next_next_index)
1411 already_connected_ =
true;
1412 ffn_[next_index] = ffn_[current_index_];
1414 else if (sfn_[next_index] == next_next_index)
1416 already_connected_ =
true;
1417 sfn_[next_index] = ffn_[current_index_];
1421 tmp_ = coords_[ffn_[next_index]] - proj_qp_;
1422 uvn_next_ffn_[0] = tmp_.dot(u_);
1423 uvn_next_ffn_[1] = tmp_.dot(v_);
1424 tmp_ = coords_[sfn_[next_index]] - proj_qp_;
1425 uvn_next_sfn_[0] = tmp_.dot(u_);
1426 uvn_next_sfn_[1] = tmp_.dot(v_);
1428 bool ffn_next_ffn =
isVisible(uvn_next_ffn_, uvn_next, uvn_current, uvn_ffn_) &&
isVisible(uvn_next_ffn_, uvn_next, uvn_next_sfn_, uvn_ffn_);
1429 bool sfn_next_ffn =
isVisible(uvn_next_sfn_, uvn_next, uvn_current, uvn_ffn_) &&
isVisible(uvn_next_sfn_, uvn_next, uvn_next_ffn_, uvn_ffn_);
1431 int connect2ffn = -1;
1432 if (ffn_next_ffn && sfn_next_ffn)
1434 double fn2f = (coords_[ffn_[current_index_]] - coords_[ffn_[next_index]]).squaredNorm ();
1435 double sn2f = (coords_[ffn_[current_index_]] - coords_[sfn_[next_index]]).squaredNorm ();
1436 if (fn2f < sn2f) connect2ffn = 0;
1437 else connect2ffn = 1;
1439 else if (ffn_next_ffn) connect2ffn = 0;
1440 else if (sfn_next_ffn) connect2ffn = 1;
1442 switch (connect2ffn)
1446 addTriangle (next_index, ffn_[current_index_], ffn_[next_index], polygons);
1447 neighbor_update = ffn_[next_index];
1450 if ((ffn_[ffn_[next_index]] == ffn_[current_index_]) || (sfn_[ffn_[next_index]] == ffn_[current_index_]))
1452 state_[ffn_[next_index]] = COMPLETED;
1454 else if (ffn_[ffn_[next_index]] == next_index)
1456 ffn_[ffn_[next_index]] = ffn_[current_index_];
1458 else if (sfn_[ffn_[next_index]] == next_index)
1460 sfn_[ffn_[next_index]] = ffn_[current_index_];
1463 ffn_[next_index] = current_index_;
1469 addTriangle (next_index, ffn_[current_index_], sfn_[next_index], polygons);
1470 neighbor_update = sfn_[next_index];
1473 if ((ffn_[sfn_[next_index]] == ffn_[current_index_]) || (sfn_[sfn_[next_index]] == ffn_[current_index_]))
1475 state_[sfn_[next_index]] = COMPLETED;
1477 else if (ffn_[sfn_[next_index]] == next_index)
1479 ffn_[sfn_[next_index]] = ffn_[current_index_];
1481 else if (sfn_[sfn_[next_index]] == next_index)
1483 sfn_[sfn_[next_index]] = ffn_[current_index_];
1486 sfn_[next_index] = current_index_;
1496 if ((ffn_[ffn_[current_index_]] == neighbor_update) || (sfn_[ffn_[current_index_]] == neighbor_update))
1498 state_[ffn_[current_index_]] = COMPLETED;
1500 else if (ffn_[ffn_[current_index_]] == current_index_)
1502 ffn_[ffn_[current_index_]] = neighbor_update;
1504 else if (sfn_[ffn_[current_index_]] == current_index_)
1506 sfn_[ffn_[current_index_]] = neighbor_update;
1510 ffn_[current_index_] = prev_index;
1516 addTriangle (current_index_, sfn_[current_index_], next_index, polygons);
1517 auto neighbor_update = next_index;
1520 if (state_[next_index] <= FREE)
1522 state_[next_index] = FRINGE;
1523 ffn_[next_index] = current_index_;
1524 sfn_[next_index] = sfn_[current_index_];
1528 if (ffn_[next_index] == R_)
1530 changed_2nd_fn_ =
true;
1531 ffn_[next_index] = sfn_[current_index_];
1533 else if (sfn_[next_index] == R_)
1535 changed_2nd_fn_ =
true;
1536 sfn_[next_index] = sfn_[current_index_];
1538 else if (next_index == R_)
1540 new2boundary_ = sfn_[current_index_];
1541 if (next_next_index == new2boundary_)
1542 already_connected_ =
true;
1544 else if (ffn_[next_index] == next_next_index)
1546 already_connected_ =
true;
1547 ffn_[next_index] = sfn_[current_index_];
1549 else if (sfn_[next_index] == next_next_index)
1551 already_connected_ =
true;
1552 sfn_[next_index] = sfn_[current_index_];
1556 tmp_ = coords_[ffn_[next_index]] - proj_qp_;
1557 uvn_next_ffn_[0] = tmp_.dot(u_);
1558 uvn_next_ffn_[1] = tmp_.dot(v_);
1559 tmp_ = coords_[sfn_[next_index]] - proj_qp_;
1560 uvn_next_sfn_[0] = tmp_.dot(u_);
1561 uvn_next_sfn_[1] = tmp_.dot(v_);
1563 bool ffn_next_sfn =
isVisible(uvn_next_ffn_, uvn_next, uvn_current, uvn_sfn_) &&
isVisible(uvn_next_ffn_, uvn_next, uvn_next_sfn_, uvn_sfn_);
1564 bool sfn_next_sfn =
isVisible(uvn_next_sfn_, uvn_next, uvn_current, uvn_sfn_) &&
isVisible(uvn_next_sfn_, uvn_next, uvn_next_ffn_, uvn_sfn_);
1566 int connect2sfn = -1;
1567 if (ffn_next_sfn && sfn_next_sfn)
1569 double fn2s = (coords_[sfn_[current_index_]] - coords_[ffn_[next_index]]).squaredNorm ();
1570 double sn2s = (coords_[sfn_[current_index_]] - coords_[sfn_[next_index]]).squaredNorm ();
1571 if (fn2s < sn2s) connect2sfn = 0;
1572 else connect2sfn = 1;
1574 else if (ffn_next_sfn) connect2sfn = 0;
1575 else if (sfn_next_sfn) connect2sfn = 1;
1577 switch (connect2sfn)
1581 addTriangle (next_index, sfn_[current_index_], ffn_[next_index], polygons);
1582 neighbor_update = ffn_[next_index];
1585 if ((ffn_[ffn_[next_index]] == sfn_[current_index_]) || (sfn_[ffn_[next_index]] == sfn_[current_index_]))
1587 state_[ffn_[next_index]] = COMPLETED;
1589 else if (ffn_[ffn_[next_index]] == next_index)
1591 ffn_[ffn_[next_index]] = sfn_[current_index_];
1593 else if (sfn_[ffn_[next_index]] == next_index)
1595 sfn_[ffn_[next_index]] = sfn_[current_index_];
1598 ffn_[next_index] = current_index_;
1604 addTriangle (next_index, sfn_[current_index_], sfn_[next_index], polygons);
1605 neighbor_update = sfn_[next_index];
1608 if ((ffn_[sfn_[next_index]] == sfn_[current_index_]) || (sfn_[sfn_[next_index]] == sfn_[current_index_]))
1610 state_[sfn_[next_index]] = COMPLETED;
1612 else if (ffn_[sfn_[next_index]] == next_index)
1614 ffn_[sfn_[next_index]] = sfn_[current_index_];
1616 else if (sfn_[sfn_[next_index]] == next_index)
1618 sfn_[sfn_[next_index]] = sfn_[current_index_];
1621 sfn_[next_index] = current_index_;
1631 if ((ffn_[sfn_[current_index_]] == neighbor_update) || (sfn_[sfn_[current_index_]] == neighbor_update))
1633 state_[sfn_[current_index_]] = COMPLETED;
1635 else if (ffn_[sfn_[current_index_]] == current_index_)
1637 ffn_[sfn_[current_index_]] = neighbor_update;
1639 else if (sfn_[sfn_[current_index_]] == current_index_)
1641 sfn_[sfn_[current_index_]] = neighbor_update;
1644 sfn_[current_index_] = prev_index;
1656 template <
typename Po
intInT> std::vector<std::vector<std::size_t> >
1661 for (std::size_t i=0; i < input.
polygons.size (); ++i)
1662 for (std::size_t j=0; j < input.
polygons[i].vertices.size (); ++j)
1663 triangleList[input.
polygons[i].vertices[j]].push_back (i);
1664 return (triangleList);
1667 #define PCL_INSTANTIATE_GreedyProjectionTriangulation(T) \
1668 template class PCL_EXPORTS pcl::GreedyProjectionTriangulation<T>;
GreedyProjectionTriangulation is an implementation of a greedy triangulation algorithm for 3D points ...
bool isVisible(const Eigen::Vector2f &X, const Eigen::Vector2f &S1, const Eigen::Vector2f &S2, const Eigen::Vector2f &R=Eigen::Vector2f::Zero())
Returns if a point X is visible from point R (or the origin) when taking into account the segment bet...
int cp(int from, int to)
Returns field copy operation code.
detail::int_type_t< detail::index_type_size, detail::index_type_signed > index_t
Type used for an index in PCL.
IndicesAllocator<> Indices
Type used for indices in PCL.
std::vector< std::uint8_t > data
std::vector< ::pcl::Vertices > polygons
::pcl::PCLPointCloud2 cloud