|
Point Cloud Library (PCL)
1.4.0
|
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
1.7.6.1