Point Cloud Library (PCL)  1.4.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
gp3.hpp
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2010, Willow Garage, Inc.
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions
00009  *  are met:
00010  *
00011  *   * Redistributions of source code must retain the above copyright
00012  *     notice, this list of conditions and the following disclaimer.
00013  *   * Redistributions in binary form must reproduce the above
00014  *     copyright notice, this list of conditions and the following
00015  *     disclaimer in the documentation and/or other materials provided
00016  *     with the distribution.
00017  *   * Neither the name of Willow Garage, Inc. nor the names of its
00018  *     contributors may be used to endorse or promote products derived
00019  *     from this software without specific prior written permission.
00020  *
00021  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032  *  POSSIBILITY OF SUCH DAMAGE.
00033  *
00034  * $Id: gp3.hpp 3753 2011-12-31 23:30:57Z rusu $
00035  *
00036  */
00037 
00038 #ifndef PCL_SURFACE_IMPL_GP3_H_
00039 #define PCL_SURFACE_IMPL_GP3_H_
00040 
00041 #include "pcl/surface/gp3.h"
00042 #include "pcl/kdtree/impl/kdtree_flann.hpp"
00043 
00045 template <typename PointInT> void
00046 pcl::GreedyProjectionTriangulation<PointInT>::performReconstruction (pcl::PolygonMesh &output)
00047 {
00048   output.polygons.clear ();
00049   output.polygons.reserve (2 * indices_->size ()); 
00050  if (!reconstructPolygons (output.polygons))
00051   {
00052     PCL_ERROR ("[pcl::%s::performReconstruction] Reconstruction failed. Check parameters: search radius (%f) or mu (%f) before continuing.\n", getClassName ().c_str (), search_radius_, mu_);
00053     output.cloud.width = output.cloud.height = 0;
00054     output.cloud.data.clear ();
00055     return;
00056   }
00057 }
00058 
00060 template <typename PointInT> void
00061 pcl::GreedyProjectionTriangulation<PointInT>::performReconstruction (std::vector<pcl::Vertices> &polygons)
00062 {
00063   polygons.clear ();
00064   polygons.reserve (2 * indices_->size ()); 
00065   if (!reconstructPolygons (polygons))
00066   {
00067     PCL_ERROR ("[pcl::%s::performReconstruction] Reconstruction failed. Check parameters: search radius (%f) or mu (%f) before continuing.\n", getClassName ().c_str (), search_radius_, mu_);
00068     return;
00069   }
00070 }
00071 
00073 template <typename PointInT> bool
00074 pcl::GreedyProjectionTriangulation<PointInT>::reconstructPolygons (std::vector<pcl::Vertices> &polygons)
00075 {
00076   if (search_radius_ <= 0 || mu_ <= 0)
00077   {
00078     polygons.clear ();
00079     return (false);
00080   }
00081   const double sqr_mu = mu_*mu_;
00082   const double sqr_max_edge = search_radius_*search_radius_;
00083   if (nnn_ > (int)indices_->size ())
00084     nnn_ = indices_->size ();
00085 
00086   // Variables to hold the results of nearest neighbor searches
00087   std::vector<int> nnIdx (nnn_);
00088   std::vector<float> sqrDists (nnn_);
00089 
00090   // current number of connected components
00091   int part_index = 0;
00092 
00093   // 2D coordinates of points
00094   const Eigen::Vector2f uvn_nn_qp_zero = Eigen::Vector2f::Zero();
00095   Eigen::Vector2f uvn_current;
00096   Eigen::Vector2f uvn_prev;
00097   Eigen::Vector2f uvn_next;
00098 
00099   // initializing fields
00100   already_connected_ = false; // see declaration for comments :P
00101 
00102   // initializing states and fringe neighbors
00103   part_.clear ();
00104   state_.clear ();
00105   source_.clear ();
00106   ffn_.clear ();
00107   sfn_.clear ();
00108   part_.resize(indices_->size (), -1); // indices of point's part
00109   state_.resize(indices_->size (), FREE);
00110   source_.resize(indices_->size (), NONE);
00111   ffn_.resize(indices_->size (), NONE);
00112   sfn_.resize(indices_->size (), NONE);
00113   fringe_queue_.clear ();
00114   int fqIdx = 0; // current fringe's index in the queue to be processed
00115 
00116   // Saving coordinates
00117   coords_.clear ();
00118   coords_.reserve (indices_->size ());
00119   for (size_t cp = 0; cp < indices_->size (); ++cp)
00120   {
00121     coords_.push_back(input_->points[(*indices_)[cp]].getVector3fMap());
00122   }
00123 
00124   // Initializing
00125   int is_free=0, nr_parts=0, increase_nnn4fn=0, increase_nnn4s=0, increase_dist=0, nr_touched = 0;
00126   bool is_fringe;
00127   angles_.resize(nnn_);
00128   std::vector<Eigen::Vector2f> uvn_nn (nnn_);
00129   Eigen::Vector2f uvn_s;
00130 
00131   // iterating through fringe points and finishing them until everything is done
00132   while (is_free != NONE)
00133   {
00134     R_ = is_free;
00135     if (state_[R_] == FREE)
00136     {
00137       state_[R_] = NONE;
00138       part_[R_] = part_index++;
00139 
00140       // creating starting triangle
00141       //searchForNeighbors ((*indices_)[R_], nnIdx, sqrDists);
00142       tree_->nearestKSearch ((*indices_)[R_], nnn_, nnIdx, sqrDists);
00143       double sqr_dist_threshold = (std::min)(sqr_max_edge, sqr_mu * sqrDists[1]);
00144 
00145       // Get the normal estimate at the current point 
00146       const Eigen::Vector3f nc = input_->points[(*indices_)[R_]].getNormalVector3fMap ();
00147 
00148       // Get a coordinate system that lies on a plane defined by its normal
00149       v_ = nc.unitOrthogonal ();
00150       u_ = nc.cross (v_);
00151 
00152       // Projecting point onto the surface 
00153       double dist = nc.dot(coords_[R_]);
00154       proj_qp_ = coords_[R_] - dist * nc;
00155 
00156       // Converting coords, calculating angles and saving the projected near boundary edges
00157       int nr_edge = 0;
00158       std::vector<doubleEdge> doubleEdges;
00159       for (int i = 1; i < nnn_; i++) // nearest neighbor with index 0 is the query point R_ itself
00160       {
00161         // Transforming coordinates
00162         tmp_ = coords_[nnIdx[i]] - proj_qp_;
00163         uvn_nn[i][0] = tmp_.dot(u_);
00164         uvn_nn[i][1] = tmp_.dot(v_);
00165         // Computing the angle between each neighboring point and the query point itself
00166         angles_[i].angle = atan2(uvn_nn[i][1], uvn_nn[i][0]);
00167         // initializing angle descriptors
00168         angles_[i].index = nnIdx[i];
00169         if (
00170             (state_[nnIdx[i]] == COMPLETED) || (state_[nnIdx[i]] == BOUNDARY)
00171             || (sqrDists[i] > sqr_dist_threshold)
00172            )
00173           angles_[i].visible = false;
00174         else
00175           angles_[i].visible = true;
00176         // Saving the edges between nearby boundary points
00177         if ((state_[nnIdx[i]] == FRINGE) || (state_[nnIdx[i]] == BOUNDARY))
00178         {
00179           doubleEdge e;
00180           e.index = i;
00181           nr_edge++;
00182           tmp_ = coords_[ffn_[nnIdx[i]]] - proj_qp_;
00183           e.first[0] = tmp_.dot(u_);
00184           e.first[1] = tmp_.dot(v_);
00185           tmp_ = coords_[sfn_[nnIdx[i]]] - proj_qp_;
00186           e.second[0] = tmp_.dot(u_);
00187           e.second[1] = tmp_.dot(v_);
00188           doubleEdges.push_back(e);
00189         }
00190       }
00191       angles_[0].visible = false;
00192 
00193       // Verify the visibility of each potential new vertex 
00194       for (int i = 1; i < nnn_; i++) // nearest neighbor with index 0 is the query point R_ itself
00195         if ((angles_[i].visible) && (ffn_[R_] != nnIdx[i]) && (sfn_[R_] != nnIdx[i]))
00196         {
00197           bool visibility = true;
00198           for (int j = 0; j < nr_edge; j++)
00199           {
00200             if (ffn_[nnIdx[doubleEdges[j].index]] != nnIdx[i])
00201               visibility = isVisible(uvn_nn[i], uvn_nn[doubleEdges[j].index], doubleEdges[j].first, Eigen::Vector2f::Zero());
00202             if (!visibility)
00203               break;
00204             if (sfn_[nnIdx[doubleEdges[j].index]] != nnIdx[i])
00205               visibility = isVisible(uvn_nn[i], uvn_nn[doubleEdges[j].index], doubleEdges[j].second, Eigen::Vector2f::Zero());
00206             if (!visibility == false)
00207               break;
00208           }
00209           angles_[i].visible = visibility;
00210         }
00211 
00212       // Selecting first two visible free neighbors
00213       bool not_found = true;
00214       int left = 1;
00215       do
00216       {
00217         while ((left < nnn_) && ((!angles_[left].visible) || (state_[nnIdx[left]] > FREE))) left++;
00218         if (left >= nnn_)
00219           break;
00220         else
00221         {
00222           int right = left+1;
00223           do
00224           {
00225             while ((right < nnn_) && ((!angles_[right].visible) || (state_[nnIdx[right]] > FREE))) right++;
00226             if (right >= nnn_)
00227               break;
00228             else if ((coords_[nnIdx[left]] - coords_[nnIdx[right]]).squaredNorm () > sqr_max_edge)
00229               right++;
00230             else
00231             {
00232               addFringePoint (nnIdx[right], R_);
00233               addFringePoint (nnIdx[left], nnIdx[right]);
00234               addFringePoint (R_, nnIdx[left]);
00235               state_[R_] = state_[nnIdx[left]] = state_[nnIdx[right]] = FRINGE;
00236               ffn_[R_] = nnIdx[left];
00237               sfn_[R_] = nnIdx[right];
00238               ffn_[nnIdx[left]] = nnIdx[right];
00239               sfn_[nnIdx[left]] = R_;
00240               ffn_[nnIdx[right]] = R_;
00241               sfn_[nnIdx[right]] = nnIdx[left];
00242               addTriangle (R_, nnIdx[left], nnIdx[right], polygons);
00243               nr_parts++;
00244               not_found = false;
00245               break;
00246             }
00247           }
00248           while (true);
00249           left++;
00250         }
00251       }
00252       while (not_found);
00253     }
00254 
00255     is_free = NONE;
00256     for (unsigned temp = 0; temp < indices_->size (); temp++)
00257     {
00258       if (state_[temp] == FREE)
00259       {
00260         is_free = temp;
00261         break;
00262       }
00263     }
00264 
00265     is_fringe = true;
00266     while (is_fringe)
00267     {
00268       is_fringe = false;
00269 
00270       int fqSize = fringe_queue_.size();
00271       while ((fqIdx < fqSize) && (state_[fringe_queue_[fqIdx]] != FRINGE))
00272         fqIdx++;
00273 
00274       // an unfinished fringe point is found
00275       if (fqIdx >= fqSize)
00276       {
00277         continue;
00278       }
00279 
00280       R_ = fringe_queue_[fqIdx];
00281       is_fringe = true;
00282 
00283       if (ffn_[R_] == sfn_[R_])
00284       {
00285         state_[R_] = COMPLETED;
00286         continue;
00287       }
00288       //searchForNeighbors ((*indices_)[R_], nnIdx, sqrDists);
00289       tree_->nearestKSearch ((*indices_)[R_], nnn_, nnIdx, sqrDists);
00290 
00291       // Locating FFN and SFN to adapt distance threshold
00292       double sqr_source_dist = (coords_[R_] - coords_[source_[R_]]).squaredNorm ();
00293       double sqr_ffn_dist = (coords_[R_] - coords_[ffn_[R_]]).squaredNorm ();
00294       double sqr_sfn_dist = (coords_[R_] - coords_[sfn_[R_]]).squaredNorm ();
00295       double max_sqr_fn_dist = (std::max)(sqr_ffn_dist, sqr_sfn_dist);
00296       double sqr_dist_threshold = (std::min)(sqr_max_edge, sqr_mu * sqrDists[1]); //sqr_mu * sqr_avg_conn_dist);
00297       if (max_sqr_fn_dist > sqrDists[nnn_-1])
00298       {
00299         if (0 == increase_nnn4fn)
00300           PCL_WARN("Not enough neighbors are considered: ffn or sfn out of range! Consider increasing nnn_... Setting R=%d to be BOUNDARY!\n", R_);
00301         increase_nnn4fn++;
00302         state_[R_] = BOUNDARY;
00303         continue;
00304       }
00305       double max_sqr_fns_dist = (std::max)(sqr_source_dist, max_sqr_fn_dist);
00306       if (max_sqr_fns_dist > sqrDists[nnn_-1])
00307       {
00308         if (0 == increase_nnn4s)
00309           PCL_WARN("Not enough neighbors are considered: source of R=%d is out of range! Consider increasing nnn_...\n", R_);
00310         increase_nnn4s++;
00311       }
00312 
00313       // Get the normal estimate at the current point 
00314       const Eigen::Vector3f nc = input_->points[(*indices_)[R_]].getNormalVector3fMap ();
00315 
00316       // Get a coordinate system that lies on a plane defined by its normal
00317       v_ = nc.unitOrthogonal ();
00318       u_ = nc.cross (v_);
00319 
00320       // Projecting point onto the surface
00321       double dist = nc.dot(coords_[R_]);
00322       proj_qp_ = coords_[R_] - dist * nc;
00323 
00324       // Converting coords, calculating angles and saving the projected near boundary edges
00325       int nr_edge = 0;
00326       std::vector<doubleEdge> doubleEdges;
00327       for (int i = 1; i < nnn_; i++) // nearest neighbor with index 0 is the query point R_ itself
00328       {
00329         tmp_ = coords_[nnIdx[i]] - proj_qp_;
00330         uvn_nn[i][0] = tmp_.dot(u_);
00331         uvn_nn[i][1] = tmp_.dot(v_);
00332   
00333         // Computing the angle between each neighboring point and the query point itself 
00334         angles_[i].angle = atan2(uvn_nn[i][1], uvn_nn[i][0]);
00335         // initializing angle descriptors
00336         angles_[i].index = nnIdx[i];
00337         angles_[i].nnIndex = i;
00338         if (
00339             (state_[nnIdx[i]] == COMPLETED) || (state_[nnIdx[i]] == BOUNDARY)
00340             || (sqrDists[i] > sqr_dist_threshold)
00341            )
00342           angles_[i].visible = false;
00343         else
00344           angles_[i].visible = true;
00345         if ((ffn_[R_] == nnIdx[i]) || (sfn_[R_] == nnIdx[i]))
00346           angles_[i].visible = true;
00347         bool same_side = true;
00348         const Eigen::Vector3f neighbor_normal = input_->points[(*indices_)[nnIdx[i]]].getNormalVector3fMap ();
00349         double cosine = nc.dot (neighbor_normal);
00350         if (cosine > 1) cosine = 1;
00351         if (cosine < -1) cosine = -1;
00352         double angle = acos (cosine);
00353         if ((!consistent_) && (angle > M_PI/2))
00354           angle = M_PI - angle;
00355         if (angle > eps_angle_)
00356         {
00357           angles_[i].visible = false;
00358           same_side = false;
00359         }
00360         // Saving the edges between nearby boundary points 
00361         if ((i!=0) && (same_side) && ((state_[nnIdx[i]] == FRINGE) || (state_[nnIdx[i]] == BOUNDARY)))
00362         {
00363           doubleEdge e;
00364           e.index = i;
00365           nr_edge++;
00366           tmp_ = coords_[ffn_[nnIdx[i]]] - proj_qp_;
00367           e.first[0] = tmp_.dot(u_);
00368           e.first[1] = tmp_.dot(v_);
00369           tmp_ = coords_[sfn_[nnIdx[i]]] - proj_qp_;
00370           e.second[0] = tmp_.dot(u_);
00371           e.second[1] = tmp_.dot(v_);
00372           doubleEdges.push_back(e);
00373           // Pruning by visibility criterion 
00374           if ((state_[nnIdx[i]] == FRINGE) && (ffn_[R_] != nnIdx[i]) && (sfn_[R_] != nnIdx[i]))
00375           {
00376             double angle1 = atan2(e.first[1] - uvn_nn[i][1], e.first[0] - uvn_nn[i][0]);
00377             double angle2 = atan2(e.second[1] - uvn_nn[i][1], e.second[0] - uvn_nn[i][0]);
00378             double angleMin, angleMax;
00379             if (angle1 < angle2)
00380             {
00381               angleMin = angle1;
00382               angleMax = angle2;
00383             }
00384             else
00385             {
00386               angleMin = angle2;
00387               angleMax = angle1;
00388             }
00389             double angleR = angles_[i].angle + M_PI;
00390             if (angleR >= 2*M_PI)
00391               angleR -= 2*M_PI;
00392             if ((source_[nnIdx[i]] == ffn_[nnIdx[i]]) || (source_[nnIdx[i]] == sfn_[nnIdx[i]]))
00393             {
00394               if ((angleMax - angleMin) < M_PI)
00395               {
00396                 if ((angleMin < angleR) && (angleR < angleMax))
00397                   angles_[i].visible = false;
00398               }
00399               else
00400               {
00401                 if ((angleR < angleMin) || (angleMax < angleR))
00402                   angles_[i].visible = false;
00403               }
00404             }
00405             else
00406             {
00407               tmp_ = coords_[source_[nnIdx[i]]] - proj_qp_;
00408               uvn_s[0] = tmp_.dot(u_);
00409               uvn_s[1] = tmp_.dot(v_);
00410               double angleS = atan2(uvn_s[1] - uvn_nn[i][1], uvn_s[0] - uvn_nn[i][0]);
00411               if ((angleMin < angleS) && (angleS < angleMax))
00412               {
00413                 if ((angleMin < angleR) && (angleR < angleMax))
00414                   angles_[i].visible = false;
00415               }
00416               else
00417               {
00418                 if ((angleR < angleMin) || (angleMax < angleR))
00419                   angles_[i].visible = false;
00420               }
00421             }
00422           }
00423         }
00424       }
00425       angles_[0].visible = false;
00426 
00427       // Verify the visibility of each potential new vertex
00428       for (int i = 1; i < nnn_; i++) // nearest neighbor with index 0 is the query point R_ itself
00429         if ((angles_[i].visible) && (ffn_[R_] != nnIdx[i]) && (sfn_[R_] != nnIdx[i]))
00430         {
00431           bool visibility = true;
00432           for (int j = 0; j < nr_edge; j++)
00433           {
00434             if (doubleEdges[j].index != i)
00435             {
00436               int f = ffn_[nnIdx[doubleEdges[j].index]];
00437               if ((f != nnIdx[i]) && (f != R_))
00438                 visibility = isVisible(uvn_nn[i], uvn_nn[doubleEdges[j].index], doubleEdges[j].first, Eigen::Vector2f::Zero());
00439               if (visibility == false)
00440                 break;
00441 
00442               int s = sfn_[nnIdx[doubleEdges[j].index]];
00443               if ((s != nnIdx[i]) && (s != R_))
00444                 visibility = isVisible(uvn_nn[i], uvn_nn[doubleEdges[j].index], doubleEdges[j].second, Eigen::Vector2f::Zero());
00445               if (visibility == false)
00446                 break;
00447             }
00448           }
00449           angles_[i].visible = visibility;
00450         }
00451 
00452       // Sorting angles
00453       std::sort (angles_.begin (), angles_.end (), GreedyProjectionTriangulation<PointInT>::nnAngleSortAsc);
00454 
00455       // Triangulating
00456       if (angles_[2].visible == false)
00457       {
00458         if ( !( (angles_[0].index == ffn_[R_] && angles_[1].index == sfn_[R_]) || (angles_[0].index == sfn_[R_] && angles_[1].index == ffn_[R_]) ) )
00459         {
00460           state_[R_] = BOUNDARY;
00461         }
00462         else
00463         {
00464           if ((source_[R_] == angles_[0].index) || (source_[R_] == angles_[1].index))
00465             state_[R_] = BOUNDARY;
00466           else
00467           {
00468             if (sqr_max_edge < (coords_[ffn_[R_]] - coords_[sfn_[R_]]).squaredNorm ())
00469             {
00470               state_[R_] = BOUNDARY;
00471             }
00472             else
00473             {
00474               tmp_ = coords_[source_[R_]] - proj_qp_;
00475               uvn_s[0] = tmp_.dot(u_);
00476               uvn_s[1] = tmp_.dot(v_);
00477               double angleS = atan2(uvn_s[1], uvn_s[0]);
00478               double dif = angles_[1].angle - angles_[0].angle;
00479               if ((angles_[0].angle < angleS) && (angleS < angles_[1].angle))
00480               {
00481                 if (dif < 2*M_PI - maximum_angle_)
00482                   state_[R_] = BOUNDARY;
00483                 else
00484                   closeTriangle (polygons);
00485               }
00486               else
00487               {
00488                 if (dif >= maximum_angle_)
00489                   state_[R_] = BOUNDARY;
00490                 else
00491                   closeTriangle (polygons);
00492               }
00493             }
00494           }
00495         }
00496         continue;
00497       }
00498 
00499       // Finding the FFN and SFN
00500       int start = -1, end = -1;
00501       for (int i=0; i<nnn_; i++)
00502       {
00503         if (ffn_[R_] == angles_[i].index)
00504         {
00505           start = i;
00506           if (sfn_[R_] == angles_[i+1].index)
00507             end = i+1;
00508           else
00509             if (i==0)
00510             {
00511               for (i = i+2; i < nnn_; i++)
00512                 if (sfn_[R_] == angles_[i].index)
00513                   break;
00514               end = i;
00515             }
00516             else
00517             {
00518               for (i = i+2; i < nnn_; i++)
00519                 if (sfn_[R_] == angles_[i].index)
00520                   break;
00521               end = i;
00522             }
00523           break;
00524         }
00525         if (sfn_[R_] == angles_[i].index)
00526         {
00527           start = i;
00528           if (ffn_[R_] == angles_[i+1].index)
00529             end = i+1;
00530           else
00531             if (i==0)
00532             {
00533               for (i = i+2; i < nnn_; i++)
00534                 if (ffn_[R_] == angles_[i].index)
00535                   break;
00536               end = i;
00537             }
00538             else
00539             {
00540               for (i = i+2; i < nnn_; i++)
00541                 if (ffn_[R_] == angles_[i].index)
00542                   break;
00543               end = i;
00544             }
00545           break;
00546         }
00547       }
00548 
00549       // start and end are always set, as we checked if ffn or sfn are out of range before, but let's check anyways if < 0
00550       if ((start < 0) || (end < 0) || (end == nnn_) || (!angles_[start].visible) || (!angles_[end].visible))
00551       {
00552         state_[R_] = BOUNDARY;
00553         continue;
00554       }
00555 
00556       // Finding last visible nn 
00557       int last_visible = end;
00558       while ((last_visible+1<nnn_) && (angles_[last_visible+1].visible)) last_visible++;
00559 
00560       // Finding visibility region of R
00561       bool need_invert = false;
00562       int sourceIdx = nnn_;
00563       if ((source_[R_] == ffn_[R_]) || (source_[R_] == sfn_[R_]))
00564       {
00565         if ((angles_[end].angle - angles_[start].angle) < M_PI)
00566           need_invert = true;
00567       }
00568       else
00569       {
00570         for (sourceIdx=0; sourceIdx<nnn_; sourceIdx++)
00571           if (angles_[sourceIdx].index == source_[R_])
00572             break;
00573         if (sourceIdx == nnn_)
00574         {
00575           int vis_free = NONE, nnCB = NONE; // any free visible and nearest completed or boundary neighbor of R
00576           for (int i = 1; i < nnn_; i++) // nearest neighbor with index 0 is the query point R_ itself
00577           {
00578             // NOTE: nnCB is an index in nnIdx
00579             if ((state_[nnIdx[i]] == COMPLETED) || (state_[nnIdx[i]] == BOUNDARY))
00580             {
00581               if (nnCB == NONE)
00582               {
00583                 nnCB = i;
00584                 if (vis_free != NONE)
00585                   break;
00586               }
00587             }
00588             // NOTE: vis_free is an index in angles
00589             if (state_[angles_[i].index] <= FREE)
00590             {
00591               if (i <= last_visible)
00592               {
00593                 vis_free = i;
00594                 if (nnCB != NONE)
00595                   break;
00596               }
00597             }
00598           }
00599           // NOTE: nCB is an index in angles
00600           int nCB = 0;
00601           if (nnCB != NONE)
00602             while (angles_[nCB].index != nnIdx[nnCB]) nCB++;
00603           else
00604             nCB = NONE;
00605 
00606           if (vis_free != NONE)
00607           {
00608             if ((vis_free < start) || (vis_free > end))
00609               need_invert = true;
00610           }
00611           else
00612           {
00613             if (nCB != NONE)
00614             {
00615               if ((nCB == start) || (nCB == end))
00616               {
00617                 bool inside_CB = false;
00618                 bool outside_CB = false;
00619                 for (int i=0; i<nnn_; i++)
00620                 {
00621                   if (
00622                       ((state_[angles_[i].index] == COMPLETED) || (state_[angles_[i].index] == BOUNDARY))
00623                       && (i != start) && (i != end)
00624                      )
00625                     {
00626                       if ((angles_[start].angle <= angles_[i].angle) && (angles_[i].angle <= angles_[end].angle))
00627                       {
00628                         inside_CB = true;
00629                         if (outside_CB)
00630                           break;
00631                       }
00632                       else
00633                       {
00634                         outside_CB = true;
00635                         if (inside_CB)
00636                           break;
00637                       }
00638                     }
00639                 }
00640                 if (inside_CB && !outside_CB)
00641                   need_invert = true;
00642                 else if (!(!inside_CB && outside_CB))
00643                 {
00644                   if ((angles_[end].angle - angles_[start].angle) < M_PI)
00645                     need_invert = true;
00646                 }
00647               }
00648               else
00649               {
00650                 if ((angles_[nCB].angle > angles_[start].angle) && (angles_[nCB].angle < angles_[end].angle))
00651                   need_invert = true;
00652               }
00653             }
00654             else
00655             {
00656               if (start == end-1)
00657                 need_invert = true;
00658             }
00659           }
00660         }
00661         else if ((angles_[start].angle < angles_[sourceIdx].angle) && (angles_[sourceIdx].angle < angles_[end].angle))
00662           need_invert = true;
00663       }
00664 
00665       // switching start and end if necessary
00666       if (need_invert)
00667       {
00668         int tmp = start;
00669         start = end;
00670         end = tmp;
00671       }
00672 
00673       // Arranging visible nnAngles in the order they need to be connected and
00674       // compute the maximal angle difference between two consecutive visible angles
00675       bool is_boundary = false, is_skinny = false;
00676       std::vector<bool> gaps (nnn_, false);
00677       std::vector<bool> skinny (nnn_, false);
00678       std::vector<double> dif (nnn_);
00679       std::vector<int> angleIdx; angleIdx.reserve (nnn_);
00680       if (start > end)
00681       {
00682         for (int j=start; j<last_visible; j++)
00683         {
00684           dif[j] = (angles_[j+1].angle - angles_[j].angle);
00685           if (dif[j] < minimum_angle_)
00686           {
00687             skinny[j] = is_skinny = true;
00688           }
00689           else if (maximum_angle_ <= dif[j])
00690           {
00691             gaps[j] = is_boundary = true;
00692           }
00693           if ((!gaps[j]) && (sqr_max_edge < (coords_[angles_[j+1].index] - coords_[angles_[j].index]).squaredNorm ()))
00694           {
00695             gaps[j] = is_boundary = true;
00696           }
00697           angleIdx.push_back(j);
00698         }
00699 
00700         dif[last_visible] = (2*M_PI + angles_[0].angle - angles_[last_visible].angle);
00701         if (dif[last_visible] < minimum_angle_)
00702         {
00703           skinny[last_visible] = is_skinny = true;
00704         }
00705         else if (maximum_angle_ <= dif[last_visible])
00706         {
00707           gaps[last_visible] = is_boundary = true;
00708         }
00709         if ((!gaps[last_visible]) && (sqr_max_edge < (coords_[angles_[0].index] - coords_[angles_[last_visible].index]).squaredNorm ()))
00710         {
00711           gaps[last_visible] = is_boundary = true;
00712         }
00713         angleIdx.push_back(last_visible);
00714 
00715         for (int j=0; j<end; j++)
00716         {
00717           dif[j] = (angles_[j+1].angle - angles_[j].angle);
00718           if (dif[j] < minimum_angle_)
00719           {
00720             skinny[j] = is_skinny = true;
00721           }
00722           else if (maximum_angle_ <= dif[j])
00723           {
00724             gaps[j] = is_boundary = true;
00725           }
00726           if ((!gaps[j]) && (sqr_max_edge < (coords_[angles_[j+1].index] - coords_[angles_[j].index]).squaredNorm ()))
00727           {
00728             gaps[j] = is_boundary = true;
00729           }
00730           angleIdx.push_back(j);
00731         }
00732         angleIdx.push_back(end);
00733       }
00734       // start < end
00735       else
00736       {
00737         for (int j=start; j<end; j++)
00738         {
00739           dif[j] = (angles_[j+1].angle - angles_[j].angle);
00740           if (dif[j] < minimum_angle_)
00741           {
00742             skinny[j] = is_skinny = true;
00743           }
00744           else if (maximum_angle_ <= dif[j])
00745           {
00746             gaps[j] = is_boundary = true;
00747           }
00748           if ((!gaps[j]) && (sqr_max_edge < (coords_[angles_[j+1].index] - coords_[angles_[j].index]).squaredNorm ()))
00749           {
00750             gaps[j] = is_boundary = true;
00751           }
00752           angleIdx.push_back(j);
00753         }
00754         angleIdx.push_back(end);
00755       }
00756 
00757       // Set the state of the point
00758       state_[R_] = is_boundary ? BOUNDARY : COMPLETED;
00759 
00760       std::vector<int>::iterator first_gap_after = angleIdx.end ();
00761       std::vector<int>::iterator last_gap_before = angleIdx.begin ();
00762       int nr_gaps = 0;
00763       for (std::vector<int>::iterator it = angleIdx.begin (); it != angleIdx.end () - 1; it++)
00764       {
00765         if (gaps[*it])
00766         {
00767           nr_gaps++;
00768           if (first_gap_after == angleIdx.end())
00769             first_gap_after = it;
00770           last_gap_before = it+1;
00771         }
00772       }
00773       if (nr_gaps > 1)
00774       {
00775         angleIdx.erase(first_gap_after+1, last_gap_before);
00776       }
00777 
00778       // Neglecting points that would form skinny triangles (if possible)
00779       if (is_skinny)
00780       {
00781         double angle_so_far = 0, angle_would_be;
00782         double max_combined_angle = (std::min)(maximum_angle_, M_PI-2*minimum_angle_);
00783         Eigen::Vector2f X;
00784         Eigen::Vector2f S1;
00785         Eigen::Vector2f S2;
00786         std::vector<int> to_erase;
00787         for (std::vector<int>::iterator it = angleIdx.begin()+1; it != angleIdx.end()-1; it++)
00788         {
00789           if (gaps[*(it-1)])
00790             angle_so_far = 0;
00791           else
00792             angle_so_far += dif[*(it-1)];
00793           if (gaps[*it])
00794             angle_would_be = angle_so_far;
00795           else
00796             angle_would_be = angle_so_far + dif[*it];
00797           if (
00798               (skinny[*it] || skinny[*(it-1)]) &&
00799               ((state_[angles_[*it].index] <= FREE) || (state_[angles_[*(it-1)].index] <= FREE)) &&
00800               ((!gaps[*it]) || (angles_[*it].nnIndex > angles_[*(it-1)].nnIndex)) &&
00801               ((!gaps[*(it-1)]) || (angles_[*it].nnIndex > angles_[*(it+1)].nnIndex)) &&
00802               (angle_would_be < max_combined_angle)
00803              )
00804           {
00805             if (gaps[*(it-1)])
00806             {
00807               gaps[*it] = true;
00808               to_erase.push_back(*it);
00809             }
00810             else if (gaps[*it])
00811             {
00812               gaps[*(it-1)] = true;
00813               to_erase.push_back(*it);
00814             }
00815             else
00816             {
00817               std::vector<int>::iterator prev_it;
00818               int erased_idx = to_erase.size()-1;
00819               for (prev_it = it-1; (erased_idx != -1) && (it != angleIdx.begin()); it--)
00820                 if (*it == to_erase[erased_idx])
00821                   erased_idx--;
00822                 else
00823                   break;
00824               bool can_delete = true;
00825               for (std::vector<int>::iterator curr_it = prev_it+1; curr_it != it+1; curr_it++)
00826               {
00827                 tmp_ = coords_[angles_[*curr_it].index] - proj_qp_;
00828                 X[0] = tmp_.dot(u_);
00829                 X[1] = tmp_.dot(v_);
00830                 tmp_ = coords_[angles_[*prev_it].index] - proj_qp_;
00831                 S1[0] = tmp_.dot(u_);
00832                 S1[1] = tmp_.dot(v_);
00833                 tmp_ = coords_[angles_[*(it+1)].index] - proj_qp_;
00834                 S2[0] = tmp_.dot(u_);
00835                 S2[1] = tmp_.dot(v_);
00836                 // check for inclusions 
00837                 if (isVisible(X,S1,S2))
00838                 {
00839                   can_delete = false;
00840                   angle_so_far = 0;
00841                   break;
00842                 }
00843               }
00844               if (can_delete)
00845               {
00846                 to_erase.push_back(*it);
00847               }
00848             }
00849           }
00850           else
00851             angle_so_far = 0;
00852         }
00853         for (std::vector<int>::iterator it = to_erase.begin(); it != to_erase.end(); it++)
00854         {
00855           for (std::vector<int>::iterator iter = angleIdx.begin(); iter != angleIdx.end(); iter++)
00856             if (*it == *iter)
00857             {
00858               angleIdx.erase(iter);
00859               break;
00860             }
00861         }
00862       }
00863 
00864       // Writing edges and updating edge-front 
00865       changed_1st_fn_ = false;
00866       changed_2nd_fn_ = false;
00867       new2boundary_ = NONE;
00868       for (std::vector<int>::iterator it = angleIdx.begin()+1; it != angleIdx.end()-1; it++)
00869       {
00870         current_index_ = angles_[*it].index;
00871 
00872         is_current_free_ = false;
00873         if (state_[current_index_] <= FREE)
00874         {
00875           state_[current_index_] = FRINGE;
00876           is_current_free_ = true;
00877         }
00878         else if (!already_connected_)
00879         {
00880           prev_is_ffn_ = (ffn_[current_index_] == angles_[*(it-1)].index) && (!gaps[*(it-1)]);
00881           prev_is_sfn_ = (sfn_[current_index_] == angles_[*(it-1)].index) && (!gaps[*(it-1)]);
00882           next_is_ffn_ = (ffn_[current_index_] == angles_[*(it+1)].index) && (!gaps[*it]);
00883           next_is_sfn_ = (sfn_[current_index_] == angles_[*(it+1)].index) && (!gaps[*it]);
00884           if (!prev_is_ffn_ && !next_is_sfn_ && !prev_is_sfn_ && !next_is_ffn_)
00885           {
00886             nr_touched++;
00887           }
00888         }
00889                                    
00890         if (gaps[*it])
00891           if (gaps[*(it-1)])
00892           {
00893             if (is_current_free_)
00894               state_[current_index_] = NONE;
00895           }
00896 
00897           else // (gaps[*it]) && ^(gaps[*(it-1)])
00898           {
00899             addTriangle (current_index_, angles_[*(it-1)].index, R_, polygons);
00900             addFringePoint (current_index_, R_);
00901             new2boundary_ = current_index_;
00902             if (!already_connected_) 
00903               connectPoint (polygons, angles_[*(it-1)].index, R_,
00904                             angles_[*(it+1)].index,
00905                             uvn_nn[angles_[*it].nnIndex], uvn_nn[angles_[*(it-1)].nnIndex], uvn_nn_qp_zero);
00906             else already_connected_ = false;
00907             if (ffn_[R_] == angles_[*(angleIdx.begin())].index)
00908             {
00909               ffn_[R_] = new2boundary_;
00910             }
00911             else if (sfn_[R_] == angles_[*(angleIdx.begin())].index)
00912             {
00913               sfn_[R_] = new2boundary_;
00914             }
00915           }
00916 
00917         else // ^(gaps[*it])
00918           if (gaps[*(it-1)])
00919           {
00920             addFringePoint (current_index_, R_);
00921             new2boundary_ = current_index_;
00922             if (!already_connected_) connectPoint (polygons, R_, angles_[*(it+1)].index,
00923                                                    (it+2) == angleIdx.end() ? -1 : angles_[*(it+2)].index,
00924                                                    uvn_nn[angles_[*it].nnIndex], uvn_nn_qp_zero, 
00925                                                    uvn_nn[angles_[*(it+1)].nnIndex]);
00926             else already_connected_ = false;
00927             if (ffn_[R_] == angles_[*(angleIdx.end()-1)].index)
00928             {
00929               ffn_[R_] = new2boundary_;
00930             }
00931             else if (sfn_[R_] == angles_[*(angleIdx.end()-1)].index)
00932             {
00933               sfn_[R_] = new2boundary_;
00934             }
00935           }
00936 
00937           else // ^(gaps[*it]) && ^(gaps[*(it-1)]) 
00938           {
00939             addTriangle (current_index_, angles_[*(it-1)].index, R_, polygons);
00940             addFringePoint (current_index_, R_);
00941             if (!already_connected_) connectPoint (polygons, angles_[*(it-1)].index, angles_[*(it+1)].index,
00942                                                    (it+2) == angleIdx.end() ? -1 : gaps[*(it+1)] ? R_ : angles_[*(it+2)].index,
00943                                                    uvn_nn[angles_[*it].nnIndex], 
00944                                                    uvn_nn[angles_[*(it-1)].nnIndex], 
00945                                                    uvn_nn[angles_[*(it+1)].nnIndex]);
00946             else already_connected_ = false;
00947           }
00948       }
00949       
00950       // Finishing up R_
00951       if (ffn_[R_] == sfn_[R_])
00952       {
00953         state_[R_] = COMPLETED;
00954       }
00955       if (!gaps[*(angleIdx.end()-2)])
00956       {
00957         addTriangle (angles_[*(angleIdx.end()-2)].index, angles_[*(angleIdx.end()-1)].index, R_, polygons);
00958         addFringePoint (angles_[*(angleIdx.end()-2)].index, R_);
00959         if (R_ == ffn_[angles_[*(angleIdx.end()-1)].index])
00960         {
00961           if (angles_[*(angleIdx.end()-2)].index == sfn_[angles_[*(angleIdx.end()-1)].index])
00962           {
00963             state_[angles_[*(angleIdx.end()-1)].index] = COMPLETED;
00964           }
00965           else
00966           {
00967             ffn_[angles_[*(angleIdx.end()-1)].index] = angles_[*(angleIdx.end()-2)].index;
00968           }
00969         }
00970         else if (R_ == sfn_[angles_[*(angleIdx.end()-1)].index])
00971         {
00972           if (angles_[*(angleIdx.end()-2)].index == ffn_[angles_[*(angleIdx.end()-1)].index])
00973           {
00974             state_[angles_[*(angleIdx.end()-1)].index] = COMPLETED;
00975           }
00976           else
00977           {
00978             sfn_[angles_[*(angleIdx.end()-1)].index] = angles_[*(angleIdx.end()-2)].index;
00979           }
00980         }
00981       }
00982       if (!gaps[*(angleIdx.begin())])
00983       {
00984         if (R_ == ffn_[angles_[*(angleIdx.begin())].index])
00985         {
00986           if (angles_[*(angleIdx.begin()+1)].index == sfn_[angles_[*(angleIdx.begin())].index])
00987           {
00988             state_[angles_[*(angleIdx.begin())].index] = COMPLETED;
00989           }
00990           else
00991           {
00992             ffn_[angles_[*(angleIdx.begin())].index] = angles_[*(angleIdx.begin()+1)].index;
00993           }
00994         }
00995         else if (R_ == sfn_[angles_[*(angleIdx.begin())].index])
00996         {
00997           if (angles_[*(angleIdx.begin()+1)].index == ffn_[angles_[*(angleIdx.begin())].index])
00998           {
00999             state_[angles_[*(angleIdx.begin())].index] = COMPLETED;
01000           }
01001           else
01002           {
01003             sfn_[angles_[*(angleIdx.begin())].index] = angles_[*(angleIdx.begin()+1)].index;
01004           }
01005         }
01006       }
01007     }
01008   }
01009   PCL_DEBUG ("Number of triangles: %d\n", (int)polygons.size());
01010   PCL_DEBUG ("Number of unconnected parts: %d\n", nr_parts);
01011   if (increase_nnn4fn > 0)
01012     PCL_WARN ("Number of neighborhood size increase requests for fringe neighbors: %d\n", increase_nnn4fn);
01013   if (increase_nnn4s > 0)
01014     PCL_WARN ("Number of neighborhood size increase requests for source: %d\n", increase_nnn4s);
01015   if (increase_dist > 0)
01016     PCL_WARN ("Number of automatic maximum distance increases: %d\n", increase_dist);
01017 
01018   // sorting and removing doubles from fringe queue 
01019   std::sort (fringe_queue_.begin (), fringe_queue_.end ());
01020   fringe_queue_.erase (std::unique (fringe_queue_.begin (), fringe_queue_.end ()), fringe_queue_.end ());
01021   PCL_DEBUG ("Number of processed points: %d / %d\n", (int)fringe_queue_.size(), (int)indices_->size ());
01022   return (true);
01023 }
01024 
01026 template <typename PointInT> void
01027 pcl::GreedyProjectionTriangulation<PointInT>::closeTriangle (std::vector<pcl::Vertices> &polygons)
01028 {
01029   state_[R_] = COMPLETED;
01030   addTriangle (angles_[0].index, angles_[1].index, R_, polygons);
01031   for (int aIdx=0; aIdx<2; aIdx++)
01032   {
01033     if (ffn_[angles_[aIdx].index] == R_)
01034     {
01035       if (sfn_[angles_[aIdx].index] == angles_[(aIdx+1)%2].index)
01036       {
01037         state_[angles_[aIdx].index] = COMPLETED;
01038       }
01039       else
01040       {
01041         ffn_[angles_[aIdx].index] = angles_[(aIdx+1)%2].index;
01042       }
01043     }
01044     else if (sfn_[angles_[aIdx].index] == R_)
01045     {
01046       if (ffn_[angles_[aIdx].index] == angles_[(aIdx+1)%2].index)
01047       {
01048         state_[angles_[aIdx].index] = COMPLETED;
01049       }
01050       else
01051       {
01052         sfn_[angles_[aIdx].index] = angles_[(aIdx+1)%2].index;
01053       }
01054     }
01055   }
01056 }
01057 
01059 template <typename PointInT> void
01060 pcl::GreedyProjectionTriangulation<PointInT>::connectPoint (
01061     std::vector<pcl::Vertices> &polygons, 
01062     const int prev_index, const int next_index, const int next_next_index, 
01063     const Eigen::Vector2f &uvn_current, 
01064     const Eigen::Vector2f &uvn_prev, 
01065     const Eigen::Vector2f &uvn_next)
01066 {
01067   if (is_current_free_)
01068   {
01069     ffn_[current_index_] = prev_index;
01070     sfn_[current_index_] = next_index;
01071   }
01072   else
01073   {
01074     if ((prev_is_ffn_ && next_is_sfn_) || (prev_is_sfn_ && next_is_ffn_))
01075       state_[current_index_] = COMPLETED;
01076     else if (prev_is_ffn_ && !next_is_sfn_)
01077       ffn_[current_index_] = next_index;
01078     else if (next_is_ffn_ && !prev_is_sfn_)
01079       ffn_[current_index_] = prev_index;
01080     else if (prev_is_sfn_ && !next_is_ffn_)
01081       sfn_[current_index_] = next_index;
01082     else if (next_is_sfn_ && !prev_is_ffn_)
01083       sfn_[current_index_] = prev_index;
01084     else
01085     {
01086       bool found_triangle = false;
01087       if ((prev_index != R_) && ((ffn_[current_index_] == ffn_[prev_index]) || (ffn_[current_index_] == sfn_[prev_index])))
01088       {
01089         found_triangle = true;
01090         addTriangle (current_index_, ffn_[current_index_], prev_index, polygons);
01091         state_[prev_index] = COMPLETED;
01092         state_[ffn_[current_index_]] = COMPLETED;
01093         ffn_[current_index_] = next_index;
01094       }
01095       else if ((prev_index != R_) && ((sfn_[current_index_] == ffn_[prev_index]) || (sfn_[current_index_] == sfn_[prev_index])))
01096       {
01097         found_triangle = true;
01098         addTriangle (current_index_, sfn_[current_index_], prev_index, polygons);
01099         state_[prev_index] = COMPLETED;
01100         state_[sfn_[current_index_]] = COMPLETED;
01101         sfn_[current_index_] = next_index;
01102       }
01103       else if (state_[next_index] > FREE)
01104       {
01105         if ((ffn_[current_index_] == ffn_[next_index]) || (ffn_[current_index_] == sfn_[next_index]))
01106         {
01107           found_triangle = true;
01108           addTriangle (current_index_, ffn_[current_index_], next_index, polygons);
01109 
01110           if (ffn_[current_index_] == ffn_[next_index])
01111           {
01112             ffn_[next_index] = current_index_;
01113           }
01114           else
01115           {
01116             sfn_[next_index] = current_index_;
01117           }
01118           state_[ffn_[current_index_]] = COMPLETED;
01119           ffn_[current_index_] = prev_index;
01120         }
01121         else if ((sfn_[current_index_] == ffn_[next_index]) || (sfn_[current_index_] == sfn_[next_index]))
01122         {
01123           found_triangle = true;
01124           addTriangle (current_index_, sfn_[current_index_], next_index, polygons);
01125 
01126           if (sfn_[current_index_] == ffn_[next_index])
01127           {
01128             ffn_[next_index] = current_index_;
01129           }
01130           else
01131           {
01132             sfn_[next_index] = current_index_;
01133           }
01134           state_[sfn_[current_index_]] = COMPLETED;
01135           sfn_[current_index_] = prev_index;
01136         }
01137       }
01138 
01139       if (found_triangle)
01140       {
01141       }
01142       else
01143       {
01144         tmp_ = coords_[ffn_[current_index_]] - proj_qp_;
01145         uvn_ffn_[0] = tmp_.dot(u_);
01146         uvn_ffn_[1] = tmp_.dot(v_);
01147         tmp_ = coords_[sfn_[current_index_]] - proj_qp_;
01148         uvn_sfn_[0] = tmp_.dot(u_);
01149         uvn_sfn_[1] = tmp_.dot(v_);
01150         bool prev_ffn = isVisible(uvn_prev, uvn_next, uvn_current, uvn_ffn_) && isVisible(uvn_prev, uvn_sfn_, uvn_current, uvn_ffn_);
01151         bool prev_sfn = isVisible(uvn_prev, uvn_next, uvn_current, uvn_sfn_) && isVisible(uvn_prev, uvn_ffn_, uvn_current, uvn_sfn_);
01152         bool next_ffn = isVisible(uvn_next, uvn_prev, uvn_current, uvn_ffn_) && isVisible(uvn_next, uvn_sfn_, uvn_current, uvn_ffn_);
01153         bool next_sfn = isVisible(uvn_next, uvn_prev, uvn_current, uvn_sfn_) && isVisible(uvn_next, uvn_ffn_, uvn_current, uvn_sfn_);
01154         int min_dist = -1;
01155         if (prev_ffn && next_sfn && prev_sfn && next_ffn)
01156         {
01157           /* should be never the case */
01158           double prev2f = (coords_[ffn_[current_index_]] - coords_[prev_index]).squaredNorm ();
01159           double next2s = (coords_[sfn_[current_index_]] - coords_[next_index]).squaredNorm ();
01160           double prev2s = (coords_[sfn_[current_index_]] - coords_[prev_index]).squaredNorm ();
01161           double next2f = (coords_[ffn_[current_index_]] - coords_[next_index]).squaredNorm ();
01162           if (prev2f < prev2s)
01163           {
01164             if (prev2f < next2f)
01165             {
01166               if (prev2f < next2s)
01167                 min_dist = 0;
01168               else
01169                 min_dist = 3;
01170             }
01171             else
01172             {
01173               if (next2f < next2s)
01174                 min_dist = 2;
01175               else
01176                 min_dist = 3;
01177             }
01178           }
01179           else
01180           {
01181             if (prev2s < next2f)
01182             {
01183               if (prev2s < next2s)
01184                 min_dist = 1;
01185               else
01186                 min_dist = 3;
01187             }
01188             else
01189             {
01190               if (next2f < next2s)
01191                 min_dist = 2;
01192               else
01193                 min_dist = 3;
01194             }
01195           }
01196         }
01197         else if (prev_ffn && next_sfn)
01198         {
01199           /* a clear case */
01200           double prev2f = (coords_[ffn_[current_index_]] - coords_[prev_index]).squaredNorm ();
01201           double next2s = (coords_[sfn_[current_index_]] - coords_[next_index]).squaredNorm ();
01202           if (prev2f < next2s)
01203             min_dist = 0;
01204           else
01205             min_dist = 3;
01206         }
01207         else if (prev_sfn && next_ffn)
01208         {
01209           /* a clear case */
01210           double prev2s = (coords_[sfn_[current_index_]] - coords_[prev_index]).squaredNorm ();
01211           double next2f = (coords_[ffn_[current_index_]] - coords_[next_index]).squaredNorm ();
01212           if (prev2s < next2f)
01213             min_dist = 1;
01214           else
01215             min_dist = 2;
01216         }
01217         /* straightforward cases */
01218         else if (prev_ffn && !next_sfn && !prev_sfn && !next_ffn)
01219           min_dist = 0;
01220         else if (!prev_ffn && !next_sfn && prev_sfn && !next_ffn)
01221           min_dist = 1;
01222         else if (!prev_ffn && !next_sfn && !prev_sfn && next_ffn)
01223           min_dist = 2;
01224         else if (!prev_ffn && next_sfn && !prev_sfn && !next_ffn)
01225           min_dist = 3;
01226         /* messed up cases */
01227         else if (prev_ffn)
01228         {
01229           double prev2f = (coords_[ffn_[current_index_]] - coords_[prev_index]).squaredNorm ();
01230           if (prev_sfn)
01231           {
01232             double prev2s = (coords_[sfn_[current_index_]] - coords_[prev_index]).squaredNorm ();
01233             if (prev2s < prev2f)
01234               min_dist = 1;
01235             else
01236               min_dist = 0;
01237           }
01238           else if (next_ffn)
01239           {
01240             double next2f = (coords_[ffn_[current_index_]] - coords_[next_index]).squaredNorm ();
01241             if (next2f < prev2f)
01242               min_dist = 2;
01243             else
01244               min_dist = 0;
01245           }
01246         }
01247         else if (next_sfn)
01248         {
01249           double next2s = (coords_[sfn_[current_index_]] - coords_[next_index]).squaredNorm ();
01250           if (prev_sfn)
01251           {
01252             double prev2s = (coords_[sfn_[current_index_]] - coords_[prev_index]).squaredNorm ();
01253             if (prev2s < next2s)
01254               min_dist = 1;
01255             else
01256               min_dist = 3;
01257           }
01258           else if (next_ffn)
01259           {
01260             double next2f = (coords_[ffn_[current_index_]] - coords_[next_index]).squaredNorm ();
01261             if (next2f < next2s)
01262               min_dist = 2;
01263             else
01264               min_dist = 3;
01265           }
01266         }
01267         switch (min_dist)
01268         {
01269           case 0://prev2f:
01270           {
01271             addTriangle (current_index_, ffn_[current_index_], prev_index, polygons);
01272 
01273             /* updating prev_index */
01274             if (ffn_[prev_index] == current_index_)
01275             {
01276               ffn_[prev_index] = ffn_[current_index_];
01277             }
01278             else if (sfn_[prev_index] == current_index_)
01279             {
01280               sfn_[prev_index] = ffn_[current_index_];
01281             }
01282             else if (ffn_[prev_index] == R_)
01283             {
01284               changed_1st_fn_ = true;
01285               ffn_[prev_index] = ffn_[current_index_];
01286             }
01287             else if (sfn_[prev_index] == R_)
01288             {
01289               changed_1st_fn_ = true;
01290               sfn_[prev_index] = ffn_[current_index_];
01291             }
01292             else if (prev_index == R_)
01293             {
01294               new2boundary_ = ffn_[current_index_];
01295             }
01296 
01297             /* updating ffn */
01298             if (ffn_[ffn_[current_index_]] == current_index_)
01299             {
01300               ffn_[ffn_[current_index_]] = prev_index;
01301             }
01302             else if (sfn_[ffn_[current_index_]] == current_index_)
01303             {
01304               sfn_[ffn_[current_index_]] = prev_index;
01305             }
01306 
01307             /* updating current */
01308             ffn_[current_index_] = next_index;
01309 
01310             break;
01311           }
01312           case 1://prev2s:
01313           {
01314             addTriangle (current_index_, sfn_[current_index_], prev_index, polygons);
01315 
01316             /* updating prev_index */
01317             if (ffn_[prev_index] == current_index_)
01318             {
01319               ffn_[prev_index] = sfn_[current_index_];
01320             }
01321             else if (sfn_[prev_index] == current_index_)
01322             {
01323               sfn_[prev_index] = sfn_[current_index_];
01324             }
01325             else if (ffn_[prev_index] == R_)
01326             {
01327               changed_1st_fn_ = true;
01328               ffn_[prev_index] = sfn_[current_index_];
01329             }
01330             else if (sfn_[prev_index] == R_)
01331             {
01332               changed_1st_fn_ = true;
01333               sfn_[prev_index] = sfn_[current_index_];
01334             }
01335             else if (prev_index == R_)
01336             {
01337               new2boundary_ = sfn_[current_index_];
01338             }
01339 
01340             /* updating sfn */
01341             if (ffn_[sfn_[current_index_]] == current_index_)
01342             {
01343               ffn_[sfn_[current_index_]] = prev_index;
01344             }
01345             else if (sfn_[sfn_[current_index_]] == current_index_)
01346             {
01347               sfn_[sfn_[current_index_]] = prev_index;
01348             }
01349 
01350             /* updating current */
01351             sfn_[current_index_] = next_index;
01352 
01353             break;
01354           }
01355           case 2://next2f:
01356           {
01357             addTriangle (current_index_, ffn_[current_index_], next_index, polygons);
01358             int neighbor_update = next_index;
01359 
01360             /* updating next_index */
01361             if (state_[next_index] <= FREE)
01362             {
01363               state_[next_index] = FRINGE;
01364               ffn_[next_index] = current_index_;
01365               sfn_[next_index] = ffn_[current_index_];
01366             }
01367             else
01368             {
01369               if (ffn_[next_index] == R_)
01370               {
01371                 changed_2nd_fn_ = true;
01372                 ffn_[next_index] = ffn_[current_index_];
01373               }
01374               else if (sfn_[next_index] == R_)
01375               {
01376                 changed_2nd_fn_ = true;
01377                 sfn_[next_index] = ffn_[current_index_];
01378               }
01379               else if (next_index == R_)
01380               {
01381                 new2boundary_ = ffn_[current_index_];
01382                 if (next_next_index == new2boundary_)
01383                   already_connected_ = true;
01384               }
01385               else if (ffn_[next_index] == next_next_index)
01386               {
01387                 already_connected_ = true;
01388                 ffn_[next_index] = ffn_[current_index_];
01389               }
01390               else if (sfn_[next_index] == next_next_index)
01391               {
01392                 already_connected_ = true;
01393                 sfn_[next_index] = ffn_[current_index_];
01394               }
01395               else
01396               {
01397                 tmp_ = coords_[ffn_[next_index]] - proj_qp_;
01398                 uvn_next_ffn_[0] = tmp_.dot(u_);
01399                 uvn_next_ffn_[1] = tmp_.dot(v_);
01400                 tmp_ = coords_[sfn_[next_index]] - proj_qp_;
01401                 uvn_next_sfn_[0] = tmp_.dot(u_);
01402                 uvn_next_sfn_[1] = tmp_.dot(v_);
01403 
01404                 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_);
01405                 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_);
01406 
01407                 int connect2ffn = -1;
01408                 if (ffn_next_ffn && sfn_next_ffn)
01409                 {
01410                   double fn2f = (coords_[ffn_[current_index_]] - coords_[ffn_[next_index]]).squaredNorm ();
01411                   double sn2f = (coords_[ffn_[current_index_]] - coords_[sfn_[next_index]]).squaredNorm ();
01412                   if (fn2f < sn2f) connect2ffn = 0;
01413                   else connect2ffn = 1;
01414                 }
01415                 else if (ffn_next_ffn) connect2ffn = 0;
01416                 else if (sfn_next_ffn) connect2ffn = 1;
01417 
01418                 switch (connect2ffn)
01419                 {
01420                   case 0: // ffn[next]
01421                   {
01422                     addTriangle (next_index, ffn_[current_index_], ffn_[next_index], polygons);
01423                     neighbor_update = ffn_[next_index];
01424 
01425                     /* ffn[next_index] */
01426                     if ((ffn_[ffn_[next_index]] == ffn_[current_index_]) || (sfn_[ffn_[next_index]] == ffn_[current_index_]))
01427                     {
01428                       state_[ffn_[next_index]] = COMPLETED;
01429                     }
01430                     else if (ffn_[ffn_[next_index]] == next_index)
01431                     {
01432                       ffn_[ffn_[next_index]] = ffn_[current_index_];
01433                     }
01434                     else if (sfn_[ffn_[next_index]] == next_index)
01435                     {
01436                       sfn_[ffn_[next_index]] = ffn_[current_index_];
01437                     }
01438 
01439                     ffn_[next_index] = current_index_;
01440 
01441                     break;
01442                   }
01443                   case 1: // sfn[next]
01444                   {
01445                     addTriangle (next_index, ffn_[current_index_], sfn_[next_index], polygons);
01446                     neighbor_update = sfn_[next_index];
01447 
01448                     /* sfn[next_index] */
01449                     if ((ffn_[sfn_[next_index]] = ffn_[current_index_]) || (sfn_[sfn_[next_index]] == ffn_[current_index_]))
01450                     {
01451                       state_[sfn_[next_index]] = COMPLETED;
01452                     }
01453                     else if (ffn_[sfn_[next_index]] == next_index)
01454                     {
01455                       ffn_[sfn_[next_index]] = ffn_[current_index_];
01456                     }
01457                     else if (sfn_[sfn_[next_index]] == next_index)
01458                     {
01459                       sfn_[sfn_[next_index]] = ffn_[current_index_];
01460                     }
01461 
01462                     sfn_[next_index] = current_index_;
01463 
01464                     break;
01465                   }
01466                   default:;
01467                 }
01468               }
01469             }
01470 
01471             /* updating ffn */
01472             if ((ffn_[ffn_[current_index_]] == neighbor_update) || (sfn_[ffn_[current_index_]] == neighbor_update))
01473             {
01474               state_[ffn_[current_index_]] = COMPLETED;
01475             }
01476             else if (ffn_[ffn_[current_index_]] == current_index_)
01477             {
01478               ffn_[ffn_[current_index_]] = neighbor_update;
01479             }
01480             else if (sfn_[ffn_[current_index_]] == current_index_)
01481             {
01482               sfn_[ffn_[current_index_]] = neighbor_update;
01483             }
01484 
01485             /* updating current */
01486             ffn_[current_index_] = prev_index;
01487 
01488             break;
01489           }
01490           case 3://next2s:
01491           {
01492             addTriangle (current_index_, sfn_[current_index_], next_index, polygons);
01493             int neighbor_update = next_index;
01494 
01495             /* updating next_index */
01496             if (state_[next_index] <= FREE)
01497             {
01498               state_[next_index] = FRINGE;
01499               ffn_[next_index] = current_index_;
01500               sfn_[next_index] = sfn_[current_index_];
01501             }
01502             else
01503             {
01504               if (ffn_[next_index] == R_)
01505               {
01506                 changed_2nd_fn_ = true;
01507                 ffn_[next_index] = sfn_[current_index_];
01508               }
01509               else if (sfn_[next_index] == R_)
01510               {
01511                 changed_2nd_fn_ = true;
01512                 sfn_[next_index] = sfn_[current_index_];
01513               }
01514               else if (next_index == R_)
01515               {
01516                 new2boundary_ = sfn_[current_index_];
01517                 if (next_next_index == new2boundary_)
01518                   already_connected_ = true;
01519               }
01520               else if (ffn_[next_index] == next_next_index)
01521               {
01522                 already_connected_ = true;
01523                 ffn_[next_index] = sfn_[current_index_];
01524               }
01525               else if (sfn_[next_index] == next_next_index)
01526               {
01527                 already_connected_ = true;
01528                 sfn_[next_index] = sfn_[current_index_];
01529               }
01530               else
01531               {
01532                 tmp_ = coords_[ffn_[next_index]] - proj_qp_;
01533                 uvn_next_ffn_[0] = tmp_.dot(u_);
01534                 uvn_next_ffn_[1] = tmp_.dot(v_);
01535                 tmp_ = coords_[sfn_[next_index]] - proj_qp_;
01536                 uvn_next_sfn_[0] = tmp_.dot(u_);
01537                 uvn_next_sfn_[1] = tmp_.dot(v_);
01538 
01539                 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_);
01540                 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_);
01541 
01542                 int connect2sfn = -1;
01543                 if (ffn_next_sfn && sfn_next_sfn)
01544                 {
01545                   double fn2s = (coords_[sfn_[current_index_]] - coords_[ffn_[next_index]]).squaredNorm ();
01546                   double sn2s = (coords_[sfn_[current_index_]] - coords_[sfn_[next_index]]).squaredNorm ();
01547                   if (fn2s < sn2s) connect2sfn = 0;
01548                   else connect2sfn = 1;
01549                 }
01550                 else if (ffn_next_sfn) connect2sfn = 0;
01551                 else if (sfn_next_sfn) connect2sfn = 1;
01552 
01553                 switch (connect2sfn)
01554                 {
01555                   case 0: // ffn[next]
01556                   {
01557                     addTriangle (next_index, sfn_[current_index_], ffn_[next_index], polygons);
01558                     neighbor_update = ffn_[next_index];
01559 
01560                     /* ffn[next_index] */
01561                     if ((ffn_[ffn_[next_index]] == sfn_[current_index_]) || (sfn_[ffn_[next_index]] == sfn_[current_index_]))
01562                     {
01563                       state_[ffn_[next_index]] = COMPLETED;
01564                     }
01565                     else if (ffn_[ffn_[next_index]] == next_index)
01566                     {
01567                       ffn_[ffn_[next_index]] = sfn_[current_index_];
01568                     }
01569                     else if (sfn_[ffn_[next_index]] == next_index)
01570                     {
01571                       sfn_[ffn_[next_index]] = sfn_[current_index_];
01572                     }
01573 
01574                     ffn_[next_index] = current_index_;
01575 
01576                     break;
01577                   }
01578                   case 1: // sfn[next]
01579                   {
01580                     addTriangle (next_index, sfn_[current_index_], sfn_[next_index], polygons);
01581                     neighbor_update = sfn_[next_index];
01582 
01583                     /* sfn[next_index] */
01584                     if ((ffn_[sfn_[next_index]] == sfn_[current_index_]) || (sfn_[sfn_[next_index]] == sfn_[current_index_]))
01585                     {
01586                       state_[sfn_[next_index]] = COMPLETED;
01587                     }
01588                     else if (ffn_[sfn_[next_index]] == next_index)
01589                     {
01590                       ffn_[sfn_[next_index]] = sfn_[current_index_];
01591                     }
01592                     else if (sfn_[sfn_[next_index]] == next_index)
01593                     {
01594                       sfn_[sfn_[next_index]] = sfn_[current_index_];
01595                     }
01596 
01597                     sfn_[next_index] = current_index_;
01598 
01599                     break;
01600                   }
01601                   default:;
01602                 }
01603               }
01604             }
01605 
01606             /* updating sfn */
01607             if ((ffn_[sfn_[current_index_]] == neighbor_update) || (sfn_[sfn_[current_index_]] == neighbor_update))
01608             {
01609               state_[sfn_[current_index_]] = COMPLETED;
01610             }
01611             else if (ffn_[sfn_[current_index_]] == current_index_)
01612             {
01613               ffn_[sfn_[current_index_]] = neighbor_update;
01614             }
01615             else if (sfn_[sfn_[current_index_]] == current_index_)
01616             {
01617               sfn_[sfn_[current_index_]] = neighbor_update;
01618             }
01619 
01620             sfn_[current_index_] = prev_index;
01621 
01622             break;
01623           }
01624           default:;
01625         }
01626       }
01627     }
01628   }
01629 }
01630 
01632 template <typename PointInT> std::vector<std::vector<size_t> >
01633 pcl::GreedyProjectionTriangulation<PointInT>::getTriangleList (const pcl::PolygonMesh &input)
01634 {
01635   std::vector<std::vector<size_t> > triangleList (input.cloud.width * input.cloud.height);
01636 
01637   for (size_t i=0; i < input.polygons.size (); ++i)
01638     for (size_t j=0; j < input.polygons[i].vertices.size (); ++j)
01639       triangleList[j].push_back (i);
01640   return (triangleList);
01641 }
01642 
01644 template <typename PointInT> void
01645 pcl::GreedyProjectionTriangulation<PointInT>::removeOverlapTriangles (
01646     pcl::PolygonMesh &mesh1,
01647     pcl::PolygonMesh &mesh2)
01648 {
01649   size_t point_size1 = mesh1.cloud.width * mesh1.cloud.height;
01650 
01651   // create new cloud
01652   pcl::PointCloud<PointInT> newcloud;
01653   pcl::PointCloud<PointInT> cloud2;
01654 
01655   pcl::fromROSMsg (mesh1.cloud, newcloud);
01656   pcl::fromROSMsg (mesh2.cloud, cloud2);
01657   newcloud += cloud2;
01658 
01659   std::vector<std::vector<size_t> > triangleList1 = getTriangleList (mesh1);
01660   std::vector<std::vector<size_t> > triangleList2 = getTriangleList (mesh1);
01661 
01662   // Variables to hold the results of nearest neighbor searches
01663   std::vector<int> nnIdx (1);
01664   std::vector<float> sqrDists (1);
01665 
01666   // for searching
01667   KdTreeFLANN<SearchPoint> kdtree;
01668 
01669   pcl::PointCloud<SearchPoint>::Ptr mycloud (new pcl::PointCloud<SearchPoint> ());
01670 
01671   Eigen::Vector3f tmp;
01672   for(size_t i=0; i< newcloud.points.size (); ++i)
01673   {
01674     tmp = newcloud.points[i].getVector3fMap();
01675     mycloud->points.push_back (SearchPoint (tmp(0), tmp(1), tmp(2)));
01676   }
01677 
01678   kdtree.setInputCloud (mycloud);
01679 
01680   Eigen::Vector3f center(0,0,0);
01681 
01682   // verties of triangle
01683   int idx[3];
01684 
01685   for (size_t i=0; i < mesh1.polygons.size(); ++i)
01686   {
01687     for (size_t j=0; j < mesh1.polygons[i].vertices.size(); ++j)
01688     {
01689       idx[j] =  mesh1.polygons[i].vertices[j];
01690       center = center + input_->points[idx[j]].getVector3fMap();
01691     }
01692     center = center/3;
01693     SearchPoint center_point(center(0), center(1), center(2));
01694 
01695     kdtree.nearestKSearch (center_point, 1, nnIdx, sqrDists);
01696 
01697     // remove the triangle if we can
01698     if (nnIdx[0] >= (int)point_size1 && triangleList2[nnIdx[0]].size() > 0)
01699     { // remove triangle
01700       for (int j = 0; j < 3; ++j)
01701       {
01702         // set vertex 1 to FREE if the triangle to be deleted was the only triangle it was in
01703         if (triangleList1[idx[j]].size() == 1)
01704         {
01705           state_[idx[j]] = FREE;
01706           sfn_[idx[j]] = -1;
01707           ffn_[idx[j]] = -1;
01708 
01709           for (int k = 0; k < 3; ++k)
01710           {
01711             // update sfn and ffn of other 2 vertices
01712             if (k != j)
01713             {
01714               if (sfn_[idx[k]] == idx[j])
01715                 sfn_[idx[k]] = idx[3- k-j];
01716               if (ffn_[idx[k]] == idx[j])
01717                 ffn_[idx[k]] = idx[3- k-j];
01718             }
01719           }// end for k
01720         }
01721         else
01722         { // set to be FRINGE
01723           state_[idx[j]] = FRINGE;
01724           // scanning other triangle that has this vertex
01725           size_t both_share_2triangles = 0;
01726           size_t last_k = 0;
01727           for (int k = 0; k < 3; ++k)
01728           {
01729             size_t share_2triangles = 0;
01730             if (k == j)
01731               continue;
01732 
01733             for (size_t p = 0; p < triangleList1[idx[j]].size(); ++p)
01734               for (size_t q =0; q < triangleList1[idx[k]].size(); ++q)
01735                 if (triangleList1[idx[j]][p] == triangleList1[idx[j]][q])
01736                   share_2triangles++;
01737 
01738             // if 2 vertex share 2 triangles
01739             if(share_2triangles == 2)
01740             {
01741               sfn_[idx[j]] = idx[k];
01742               ffn_[idx[j]] = idx[k];
01743               both_share_2triangles++;
01744               last_k = k;
01745             }
01746           }
01747           // if both share 2 triangles
01748           if (both_share_2triangles == 2)
01749           {
01750             // change ffn or sfn
01751             ffn_[idx[j]] = idx[3-j-last_k];
01752           }
01753         }
01754 
01755       }// end for j
01756     }// end if
01757   }// end fo i
01758 }
01759 
01760 #define PCL_INSTANTIATE_GreedyProjectionTriangulation(T)                \
01761   template class PCL_EXPORTS pcl::GreedyProjectionTriangulation<T>;
01762 
01763 #endif    // PCL_SURFACE_IMPL_GP3_H_
01764 
01765 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines