|
Point Cloud Library (PCL)
1.5.1
|
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: grid_projection.hpp 4702 2012-02-23 09:39:33Z gedikli $ 00035 * 00036 */ 00037 00038 #ifndef PCL_SURFACE_IMPL_GRID_PROJECTION_H_ 00039 #define PCL_SURFACE_IMPL_GRID_PROJECTION_H_ 00040 00041 #include "pcl/surface/grid_projection.h" 00042 #include <pcl/common/common.h> 00043 #include <pcl/common/centroid.h> 00044 #include <pcl/common/vector_average.h> 00045 #include <pcl/Vertices.h> 00046 00048 template <typename PointNT> 00049 pcl::GridProjection<PointNT>::GridProjection () : 00050 leaf_size_(0.001), data_size_(0), max_binary_search_level_(10), k_(50), padding_size_(3), data_() 00051 {} 00052 00054 template <typename PointNT> 00055 pcl::GridProjection<PointNT>::GridProjection (double resolution) : 00056 leaf_size_(resolution), data_size_(0), max_binary_search_level_(10), k_(50), padding_size_(3), data_() 00057 {} 00058 00060 template <typename PointNT> 00061 pcl::GridProjection<PointNT>::~GridProjection () 00062 { 00063 vector_at_data_point_.clear (); 00064 surface_.clear ();; 00065 cell_hash_map_.clear (); 00066 occupied_cell_list_.clear (); 00067 data_.reset (); 00068 } 00069 00071 template <typename PointNT> void 00072 pcl::GridProjection<PointNT>::scaleInputDataPoint (double scale_factor) 00073 { 00074 for (size_t i = 0; i < data_->points.size(); ++i) 00075 data_->points[i].getVector4fMap () /= scale_factor; 00076 max_p_ /= scale_factor; 00077 min_p_ /= scale_factor; 00078 } 00079 00081 template <typename PointNT> void 00082 pcl::GridProjection<PointNT>::getBoundingBox () 00083 { 00084 pcl::getMinMax3D (*data_, min_p_, max_p_); 00085 00086 Eigen::Vector4f bounding_box_size = max_p_ - min_p_; 00087 double scale_factor = (std::max)((std::max)(bounding_box_size.x (), 00088 bounding_box_size.y ()), 00089 bounding_box_size.z ()); 00090 if (scale_factor > 1) 00091 scaleInputDataPoint (scale_factor); 00092 00093 // Round the max_p_, min_p_ so that they are aligned with the cells vertices 00094 int upper_right_index[3]; 00095 int lower_left_index[3]; 00096 for (size_t i = 0; i < 3; ++i) 00097 { 00098 upper_right_index[i] = max_p_(i) / leaf_size_ + 5; 00099 lower_left_index[i] = min_p_(i) / leaf_size_ - 5; 00100 max_p_(i) = upper_right_index[i] * leaf_size_; 00101 min_p_(i) = lower_left_index[i] * leaf_size_; 00102 } 00103 bounding_box_size = max_p_ - min_p_; 00104 PCL_DEBUG ("[pcl::GridProjection::getBoundingBox] Size of Bounding Box is [%f, %f, %f]\n", 00105 bounding_box_size.x (), bounding_box_size.y (), bounding_box_size.z ()); 00106 double max_size = 00107 (std::max) ((std::max)(bounding_box_size.x (), bounding_box_size.y ()), 00108 bounding_box_size.z ()); 00109 00110 data_size_ = max_size / leaf_size_; 00111 PCL_DEBUG ("[pcl::GridProjection::getBoundingBox] Lower left point is [%f, %f, %f]\n", 00112 min_p_.x (), min_p_.y (), min_p_.z ()); 00113 PCL_DEBUG ("[pcl::GridProjection::getBoundingBox] Upper left point is [%f, %f, %f]\n", 00114 max_p_.x (), max_p_.y (), max_p_.z ()); 00115 PCL_DEBUG ("[pcl::GridProjection::getBoundingBox] Padding size: %d\n", padding_size_); 00116 PCL_DEBUG ("[pcl::GridProjection::getBoundingBox] Leaf size: %f\n", leaf_size_); 00117 occupied_cell_list_.resize (data_size_ * data_size_ * data_size_); 00118 gaussian_scale_ = pow ((padding_size_+1) * leaf_size_ / 2.0, 2.0); 00119 } 00120 00122 template <typename PointNT> void 00123 pcl::GridProjection<PointNT>::getVertexFromCellCenter ( 00124 const Eigen::Vector4f &cell_center, 00125 std::vector<Eigen::Vector4f, Eigen::aligned_allocator<Eigen::Vector4f> > &pts) const 00126 { 00127 assert (pts.size () == 8); 00128 00129 float sz = leaf_size_ / 2.0; 00130 00131 pts[0] = cell_center + Eigen::Vector4f (-sz, sz, -sz, 0); 00132 pts[1] = cell_center + Eigen::Vector4f (-sz, -sz, -sz, 0); 00133 pts[2] = cell_center + Eigen::Vector4f (sz, -sz, -sz, 0); 00134 pts[3] = cell_center + Eigen::Vector4f (sz, sz, -sz, 0); 00135 pts[4] = cell_center + Eigen::Vector4f (-sz, sz, sz, 0); 00136 pts[5] = cell_center + Eigen::Vector4f (-sz, -sz, sz, 0); 00137 pts[6] = cell_center + Eigen::Vector4f (sz, -sz, sz, 0); 00138 pts[7] = cell_center + Eigen::Vector4f (sz, sz, sz, 0); 00139 } 00140 00142 template <typename PointNT> void 00143 pcl::GridProjection<PointNT>::getDataPtsUnion (const Eigen::Vector3i &index, 00144 std::vector <int> &pt_union_indices) 00145 { 00146 for (int i = index[0] - padding_size_; i <= index[0] + padding_size_; ++i) 00147 { 00148 for (int j = index[1] - padding_size_; j <= index[1] + padding_size_; ++j) 00149 { 00150 for (int k = index[2] - padding_size_; k <= index[2] + padding_size_; ++k) 00151 { 00152 Eigen::Vector3i cell_index_3d (i, j, k); 00153 int cell_index_1d = getIndexIn1D (cell_index_3d); 00154 if (cell_hash_map_.find (cell_index_1d) != cell_hash_map_.end ()) 00155 { 00156 // Get the indices of the input points within the cell(i,j,k), which 00157 // is stored in the hash map 00158 pt_union_indices.insert (pt_union_indices.end (), 00159 cell_hash_map_.at (cell_index_1d).data_indices.begin (), 00160 cell_hash_map_.at (cell_index_1d).data_indices.end ()); 00161 } 00162 } 00163 } 00164 } 00165 } 00166 00168 template <typename PointNT> void 00169 pcl::GridProjection<PointNT>::createSurfaceForCell (const Eigen::Vector3i &index, 00170 std::vector <int> &pt_union_indices) 00171 { 00172 // 8 vertices of the cell 00173 std::vector<Eigen::Vector4f, Eigen::aligned_allocator<Eigen::Vector4f> > vertices (8); 00174 00175 // 4 end points that shared by 3 edges connecting the upper left front points 00176 Eigen::Vector4f pts[4]; 00177 Eigen::Vector3f vector_at_pts[4]; 00178 00179 // Given the index of cell, caluate the coordinates of the eight vertices of the cell 00180 // index the index of the cell in (x,y,z) 3d format 00181 Eigen::Vector4f cell_center = Eigen::Vector4f::Zero (); 00182 getCellCenterFromIndex (index, cell_center); 00183 getVertexFromCellCenter (cell_center, vertices); 00184 00185 // Get the indices of the cells which stores the 4 end points. 00186 Eigen::Vector3i indices[4]; 00187 indices[0] = Eigen::Vector3i (index[0], index[1], index[2] - 1); 00188 indices[1] = Eigen::Vector3i (index[0], index[1], index[2]); 00189 indices[2] = Eigen::Vector3i (index[0], index[1] - 1, index[2]); 00190 indices[3] = Eigen::Vector3i (index[0] + 1, index[1], index[2]); 00191 00192 // Get the coordinate of the 4 end points, and the corresponding vectors 00193 for (size_t i = 0; i < 4; ++i) 00194 { 00195 pts[i] = vertices[I_SHIFT_PT[i]]; 00196 unsigned int index_1d = getIndexIn1D (indices[i]); 00197 if (cell_hash_map_.find (index_1d) == cell_hash_map_.end () || 00198 occupied_cell_list_[index_1d] == 0) 00199 return; 00200 else 00201 vector_at_pts[i] = cell_hash_map_.at (index_1d).vect_at_grid_pt; 00202 } 00203 00204 // Go through the 3 edges, test whether they are intersected by the surface 00205 for (size_t i = 0; i < 3; ++i) 00206 { 00207 std::vector<Eigen::Vector4f, Eigen::aligned_allocator<Eigen::Vector4f> > end_pts (2); 00208 std::vector<Eigen::Vector3f, Eigen::aligned_allocator<Eigen::Vector3f> > vect_at_end_pts (2); 00209 for (size_t j = 0; j < 2; ++j) 00210 { 00211 end_pts[j] = pts[I_SHIFT_EDGE[i][j]]; 00212 vect_at_end_pts[j] = vector_at_pts[I_SHIFT_EDGE[i][j]]; 00213 } 00214 if (isIntersected (end_pts, vect_at_end_pts, pt_union_indices)) 00215 { 00216 // Indices of cells that contains points which will be connected to 00217 // create a polygon 00218 Eigen::Vector3i polygon[4]; 00219 Eigen::Vector4f polygon_pts[4]; 00220 int polygon_indices_1d[4]; 00221 bool is_all_in_hash_map = true; 00222 switch (i) 00223 { 00224 case 0: 00225 polygon[0] = Eigen::Vector3i (index[0] - 1, index[1] + 1, index[2]); 00226 polygon[1] = Eigen::Vector3i (index[0] - 1, index[1], index[2]); 00227 polygon[2] = Eigen::Vector3i (index[0], index[1], index[2]); 00228 polygon[3] = Eigen::Vector3i (index[0], index[1] + 1, index[2]); 00229 break; 00230 case 1: 00231 polygon[0] = Eigen::Vector3i (index[0], index[1] + 1, index[2] + 1); 00232 polygon[1] = Eigen::Vector3i (index[0], index[1] + 1, index[2]); 00233 polygon[2] = Eigen::Vector3i (index[0], index[1], index[2]); 00234 polygon[3] = Eigen::Vector3i (index[0], index[1], index[2] + 1); 00235 break; 00236 case 2: 00237 polygon[0] = Eigen::Vector3i (index[0] - 1, index[1], index[2] + 1); 00238 polygon[1] = Eigen::Vector3i (index[0] - 1, index[1], index[2]); 00239 polygon[2] = Eigen::Vector3i (index[0], index[1], index[2]); 00240 polygon[3] = Eigen::Vector3i (index[0], index[1], index[2] + 1); 00241 break; 00242 default: 00243 break; 00244 } 00245 for (size_t k = 0; k < 4; k++) 00246 { 00247 polygon_indices_1d[k] = getIndexIn1D (polygon[k]); 00248 if (!occupied_cell_list_[polygon_indices_1d[k]]) 00249 { 00250 is_all_in_hash_map = false; 00251 break; 00252 } 00253 } 00254 if (is_all_in_hash_map) 00255 { 00256 for (size_t k = 0; k < 4; k++) 00257 { 00258 polygon_pts[k] = cell_hash_map_.at (polygon_indices_1d[k]).pt_on_surface; 00259 surface_.push_back (polygon_pts[k]); 00260 } 00261 } 00262 } 00263 } 00264 } 00265 00267 template <typename PointNT> void 00268 pcl::GridProjection<PointNT>::getProjection (const Eigen::Vector4f &p, 00269 std::vector <int> &pt_union_indices, Eigen::Vector4f &projection) 00270 { 00271 const double projection_distance = leaf_size_ * 3; 00272 std::vector<Eigen::Vector4f, Eigen::aligned_allocator<Eigen::Vector4f> > end_pt (2); 00273 std::vector<Eigen::Vector3f, Eigen::aligned_allocator<Eigen::Vector3f> > end_pt_vect (2); 00274 end_pt[0] = p; 00275 getVectorAtPoint (end_pt[0], pt_union_indices, end_pt_vect[0]); 00276 end_pt_vect[0].normalize(); 00277 00278 double dSecond = getD2AtPoint (end_pt[0], end_pt_vect[0], pt_union_indices); 00279 00280 // Find another point which is projection_distance away from the p, do a 00281 // binary search between these two points, to find the projected point on the 00282 // surface 00283 if (dSecond > 0) 00284 end_pt[1] = end_pt[0] + Eigen::Vector4f (end_pt_vect[0][0] * projection_distance, 00285 end_pt_vect[0][1] * projection_distance, 00286 end_pt_vect[0][2] * projection_distance, 0); 00287 else 00288 end_pt[1] = end_pt[0] - Eigen::Vector4f (end_pt_vect[0][0] * projection_distance, 00289 end_pt_vect[0][1] * projection_distance, 00290 end_pt_vect[0][2] * projection_distance, 0); 00291 getVectorAtPoint (end_pt[1], pt_union_indices, end_pt_vect[1]); 00292 if (end_pt_vect[1].dot (end_pt_vect[0]) < 0) 00293 { 00294 Eigen::Vector4f mid_pt = end_pt[0] + (end_pt[1] - end_pt[0]) * 0.5; 00295 findIntersection (0, end_pt, end_pt_vect, mid_pt, pt_union_indices, projection); 00296 } 00297 else 00298 projection = p; 00299 } 00300 00302 template <typename PointNT> void 00303 pcl::GridProjection<PointNT>::getProjectionWithPlaneFit (const Eigen::Vector4f &p, 00304 std::vector<int> (&pt_union_indices), 00305 Eigen::Vector4f &projection) 00306 { 00307 // Compute the plane coefficients 00308 Eigen::Vector4f model_coefficients; 00310 Eigen::Matrix3f covariance_matrix; 00311 Eigen::Vector4f xyz_centroid; 00312 00313 computeMeanAndCovarianceMatrix (*data_, pt_union_indices, covariance_matrix, xyz_centroid); 00314 00315 // Get the plane normal 00316 EIGEN_ALIGN16 Eigen::Vector3f::Scalar eigen_value; 00317 EIGEN_ALIGN16 Eigen::Vector3f eigen_vector; 00318 pcl::eigen33 (covariance_matrix, eigen_value, eigen_vector); 00319 00320 // The normalization is not necessary, since the eigenvectors from libeigen are already normalized 00321 model_coefficients[0] = eigen_vector [0]; 00322 model_coefficients[1] = eigen_vector [1]; 00323 model_coefficients[2] = eigen_vector [2]; 00324 model_coefficients[3] = 0; 00325 // Hessian form (D = nc . p_plane (centroid here) + p) 00326 model_coefficients[3] = -1 * model_coefficients.dot (xyz_centroid); 00327 00328 // Projected point 00329 Eigen::Vector3f point (p.x (), p.y (), p.z ()); //= Eigen::Vector3f::MapAligned (&output.points[cp].x, 3); 00330 float distance = point.dot (model_coefficients.head <3> ()) + model_coefficients[3]; 00331 point -= distance * model_coefficients.head < 3 > (); 00332 00333 projection = Eigen::Vector4f (point[0], point[1], point[2], 0); 00334 } 00335 00337 template <typename PointNT> void 00338 pcl::GridProjection<PointNT>::getVectorAtPoint (const Eigen::Vector4f &p, 00339 std::vector <int> &pt_union_indices, 00340 Eigen::Vector3f &vo) 00341 { 00342 std::vector <double> pt_union_dist (pt_union_indices.size ()); 00343 std::vector <double> pt_union_weight (pt_union_indices.size ()); 00344 Eigen::Vector3f out_vector (0, 0, 0); 00345 double sum = 0.0; 00346 double mag = 0.0; 00347 00348 for (size_t i = 0; i < pt_union_indices.size (); ++i) 00349 { 00350 pt_union_dist[i] = (data_->points[pt_union_indices[i]].getVector4fMap () - p).squaredNorm (); 00351 pt_union_weight[i] = pow (M_E, -pow (pt_union_dist[i], 2.0) / gaussian_scale_); 00352 mag += pow (M_E, -pow (sqrt (pt_union_dist[i]), 2.0) / gaussian_scale_); 00353 sum += pt_union_weight[i]; 00354 } 00355 00356 pcl::VectorAverage3f vector_average; 00357 00358 Eigen::Vector3f v (data_->points[pt_union_indices[0]].normal[0], 00359 data_->points[pt_union_indices[0]].normal[1], 00360 data_->points[pt_union_indices[0]].normal[2]); 00361 00362 for (size_t i = 0; i < pt_union_weight.size (); ++i) 00363 { 00364 pt_union_weight[i] /= sum; 00365 Eigen::Vector3f vec (data_->points[pt_union_indices[i]].normal[0], 00366 data_->points[pt_union_indices[i]].normal[1], 00367 data_->points[pt_union_indices[i]].normal[2]); 00368 if (vec.dot (v) < 0) 00369 vec = -vec; 00370 vector_average.add (vec, pt_union_weight[i]); 00371 } 00372 out_vector = vector_average.getMean (); 00373 // vector_average.getEigenVector1(out_vector); 00374 00375 out_vector.normalize (); 00376 double d1 = getD1AtPoint (p, out_vector, pt_union_indices); 00377 out_vector = out_vector * sum; 00378 vo = ((d1 > 0) ? -1 : 1) * out_vector; 00379 } 00380 00382 template <typename PointNT> void 00383 pcl::GridProjection<PointNT>::getVectorAtPointKNN (const Eigen::Vector4f &p, 00384 std::vector <int> &k_indices, 00385 std::vector <float> &k_squared_distances, 00386 Eigen::Vector3f &vo) 00387 { 00388 Eigen::Vector3f out_vector (0, 0, 0); 00389 std::vector <float> k_weight; 00390 k_weight.resize (k_); 00391 float sum = 0.0; 00392 for (int i = 0; i < k_; i++) 00393 { 00394 //k_weight[i] = pow (M_E, -pow (k_squared_distances[i], 2.0) / gaussian_scale_); 00395 k_weight[i] = std::pow (static_cast<float>(M_E), static_cast<float>(-pow (static_cast<float>(k_squared_distances[i]), 2.0f) / gaussian_scale_)); 00396 sum += k_weight[i]; 00397 } 00398 pcl::VectorAverage3f vector_average; 00399 for (int i = 0; i < k_; i++) 00400 { 00401 k_weight[i] /= sum; 00402 Eigen::Vector3f vec (data_->points[k_indices[i]].normal[0], 00403 data_->points[k_indices[i]].normal[1], 00404 data_->points[k_indices[i]].normal[2]); 00405 vector_average.add (vec, k_weight[i]); 00406 } 00407 vector_average.getEigenVector1 (out_vector); 00408 out_vector.normalize (); 00409 double d1 = getD1AtPoint (p, out_vector, k_indices); 00410 out_vector = out_vector * sum; 00411 vo = ((d1 > 0) ? -1 : 1) * out_vector; 00412 00413 } 00414 00416 template <typename PointNT> double 00417 pcl::GridProjection<PointNT>::getMagAtPoint (const Eigen::Vector4f &p, 00418 const std::vector <int> &pt_union_indices) 00419 { 00420 std::vector <double> pt_union_dist (pt_union_indices.size ()); 00421 std::vector <double> pt_union_weight (pt_union_indices.size ()); 00422 double sum = 0.0; 00423 for (size_t i = 0; i < pt_union_indices.size (); ++i) 00424 { 00425 pt_union_dist[i] = (data_->points[pt_union_indices[i]].getVector4fMap () - p).norm (); 00426 sum += pow (M_E, -pow (pt_union_dist[i], 2.0) / gaussian_scale_); 00427 } 00428 return (sum); 00429 } 00430 00432 template <typename PointNT> double 00433 pcl::GridProjection<PointNT>::getD1AtPoint (const Eigen::Vector4f &p, const Eigen::Vector3f &vec, 00434 const std::vector <int> &pt_union_indices) 00435 { 00436 double sz = 0.01 * leaf_size_; 00437 Eigen::Vector3f v = vec * sz; 00438 00439 double forward = getMagAtPoint (p + Eigen::Vector4f (v[0], v[1], v[2], 0), pt_union_indices); 00440 double backward = getMagAtPoint (p - Eigen::Vector4f (v[0], v[1], v[2], 0), pt_union_indices); 00441 return ((forward - backward) / (0.02 * leaf_size_)); 00442 } 00443 00445 template <typename PointNT> double 00446 pcl::GridProjection<PointNT>::getD2AtPoint (const Eigen::Vector4f &p, const Eigen::Vector3f &vec, 00447 const std::vector <int> &pt_union_indices) 00448 { 00449 double sz = 0.01 * leaf_size_; 00450 Eigen::Vector3f v = vec * sz; 00451 00452 double forward = getD1AtPoint (p + Eigen::Vector4f (v[0], v[1], v[2], 0), vec, pt_union_indices); 00453 double backward = getD1AtPoint (p - Eigen::Vector4f (v[0], v[1], v[2], 0), vec, pt_union_indices); 00454 return ((forward - backward) / (0.02 * leaf_size_)); 00455 } 00456 00458 template <typename PointNT> bool 00459 pcl::GridProjection<PointNT>::isIntersected (const std::vector<Eigen::Vector4f, Eigen::aligned_allocator<Eigen::Vector4f> > &end_pts, 00460 std::vector<Eigen::Vector3f, Eigen::aligned_allocator<Eigen::Vector3f> > &vect_at_end_pts, 00461 std::vector <int> &pt_union_indices) 00462 { 00463 assert (end_pts.size () == 2); 00464 assert (vect_at_end_pts.size () == 2); 00465 00466 double length[2]; 00467 for (size_t i = 0; i < 2; ++i) 00468 { 00469 length[i] = vect_at_end_pts[i].norm (); 00470 vect_at_end_pts[i].normalize (); 00471 } 00472 double dot_prod = vect_at_end_pts[0].dot (vect_at_end_pts[1]); 00473 if (dot_prod < 0) 00474 { 00475 double ratio = length[0] / (length[0] + length[1]); 00476 Eigen::Vector4f start_pt = end_pts[0] + (end_pts[1] - end_pts[0]) * ratio; 00477 Eigen::Vector4f intersection_pt = Eigen::Vector4f::Zero (); 00478 findIntersection (0, end_pts, vect_at_end_pts, start_pt, pt_union_indices, intersection_pt); 00479 00480 Eigen::Vector3f vec; 00481 getVectorAtPoint (intersection_pt, pt_union_indices, vec); 00482 vec.normalize (); 00483 00484 double d2 = getD2AtPoint (intersection_pt, vec, pt_union_indices); 00485 if (d2 < 0) 00486 return (true); 00487 } 00488 return (false); 00489 } 00490 00492 template <typename PointNT> void 00493 pcl::GridProjection<PointNT>::findIntersection (int level, 00494 const std::vector<Eigen::Vector4f, Eigen::aligned_allocator<Eigen::Vector4f> > &end_pts, 00495 const std::vector<Eigen::Vector3f, Eigen::aligned_allocator<Eigen::Vector3f> > &vect_at_end_pts, 00496 const Eigen::Vector4f &start_pt, 00497 std::vector <int> &pt_union_indices, 00498 Eigen::Vector4f &intersection) 00499 { 00500 assert (end_pts.size () == 2); 00501 assert (vect_at_end_pts.size () == 2); 00502 00503 Eigen::Vector3f vec; 00504 getVectorAtPoint (start_pt, pt_union_indices, vec); 00505 double d1 = getD1AtPoint (start_pt, vec, pt_union_indices); 00506 std::vector<Eigen::Vector4f, Eigen::aligned_allocator<Eigen::Vector4f> > new_end_pts (2); 00507 std::vector<Eigen::Vector3f, Eigen::aligned_allocator<Eigen::Vector3f> > new_vect_at_end_pts (2); 00508 if ((abs (d1) < 10e-3) || (level == max_binary_search_level_)) 00509 { 00510 intersection = start_pt; 00511 return; 00512 } 00513 else 00514 { 00515 vec.normalize (); 00516 if (vec.dot (vect_at_end_pts[0]) < 0) 00517 { 00518 Eigen::Vector4f new_start_pt = end_pts[0] + (start_pt - end_pts[0]) * 0.5; 00519 new_end_pts[0] = end_pts[0]; 00520 new_end_pts[1] = start_pt; 00521 new_vect_at_end_pts[0] = vect_at_end_pts[0]; 00522 new_vect_at_end_pts[1] = vec; 00523 findIntersection (level + 1, new_end_pts, new_vect_at_end_pts, new_start_pt, pt_union_indices, intersection); 00524 return; 00525 } 00526 if (vec.dot (vect_at_end_pts[1]) < 0) 00527 { 00528 Eigen::Vector4f new_start_pt = start_pt + (end_pts[1] - start_pt) * 0.5; 00529 new_end_pts[0] = start_pt; 00530 new_end_pts[1] = end_pts[1]; 00531 new_vect_at_end_pts[0] = vec; 00532 new_vect_at_end_pts[1] = vect_at_end_pts[1]; 00533 findIntersection (level + 1, new_end_pts, new_vect_at_end_pts, new_start_pt, pt_union_indices, intersection); 00534 return; 00535 } 00536 intersection = start_pt; 00537 return; 00538 } 00539 } 00540 00541 00543 template <typename PointNT> void 00544 pcl::GridProjection<PointNT>::fillPad (const Eigen::Vector3i &index) 00545 { 00546 for (int i = index[0] - padding_size_; i < index[0] + padding_size_; ++i) 00547 { 00548 for (int j = index[1] - padding_size_; j < index[1] + padding_size_; ++j) 00549 { 00550 for (int k = index[2] - padding_size_; k < index[2] + padding_size_; ++k) 00551 { 00552 Eigen::Vector3i cell_index_3d (i, j, k); 00553 unsigned int cell_index_1d = getIndexIn1D (cell_index_3d); 00554 if (cell_hash_map_.find (cell_index_1d) == cell_hash_map_.end ()) 00555 { 00556 cell_hash_map_[cell_index_1d].data_indices.resize (0); 00557 getCellCenterFromIndex (cell_index_3d, cell_hash_map_[cell_index_1d].pt_on_surface); 00558 } 00559 } 00560 } 00561 } 00562 } 00563 00564 00566 template <typename PointNT> void 00567 pcl::GridProjection<PointNT>::storeVectAndSurfacePoint (int index_1d, 00568 const Eigen::Vector3i &index_3d, 00569 std::vector <int> &pt_union_indices, 00570 const Leaf &cell_data) 00571 { 00572 // Get point on grid 00573 Eigen::Vector4f grid_pt (cell_data.pt_on_surface.x () - leaf_size_ / 2.0, 00574 cell_data.pt_on_surface.y () + leaf_size_ / 2.0, 00575 cell_data.pt_on_surface.z () + leaf_size_ / 2.0, 0); 00576 00577 // Save the vector and the point on the surface 00578 getVectorAtPoint (grid_pt, pt_union_indices, cell_hash_map_[index_1d].vect_at_grid_pt); 00579 getProjection (cell_data.pt_on_surface, pt_union_indices, cell_hash_map_[index_1d].pt_on_surface); 00580 } 00581 00583 template <typename PointNT> void 00584 pcl::GridProjection<PointNT>::storeVectAndSurfacePointKNN (int index_1d, const Eigen::Vector3i &index_3d, 00585 const Leaf &cell_data) 00586 { 00587 Eigen::Vector4f cell_center = cell_data.pt_on_surface; 00588 Eigen::Vector4f grid_pt (cell_center.x () - leaf_size_ / 2, 00589 cell_center.y () + leaf_size_ / 2, 00590 cell_center.z () + leaf_size_ / 2, 0); 00591 00592 std::vector <int> k_indices; 00593 k_indices.resize (k_); 00594 std::vector <float> k_squared_distances; 00595 k_squared_distances.resize (k_); 00596 00597 PointNT pt; pt.x = grid_pt.x (); pt.y = grid_pt.y (); pt.z = grid_pt.z (); 00598 tree_->nearestKSearch (pt, k_, k_indices, k_squared_distances); 00599 00600 getVectorAtPointKNN (grid_pt, k_indices, k_squared_distances, cell_hash_map_[index_1d].vect_at_grid_pt); 00601 getProjectionWithPlaneFit (cell_center, k_indices, cell_hash_map_[index_1d].pt_on_surface); 00602 } 00603 00605 template <typename PointNT> bool 00606 pcl::GridProjection<PointNT>::reconstructPolygons (std::vector<pcl::Vertices> &polygons) 00607 { 00608 data_.reset (new pcl::PointCloud<PointNT> (*input_)); 00609 getBoundingBox (); 00610 00611 // Store the point cloud data into the voxel grid, and at the same time 00612 // create a hash map to store the information for each cell 00613 cell_hash_map_.max_load_factor (2.0); 00614 cell_hash_map_.rehash (data_->points.size () / cell_hash_map_.max_load_factor ()); 00615 00616 // Go over all points and insert them into the right leaf 00617 for (size_t cp = 0; cp < data_->points.size (); ++cp) 00618 { 00619 // Check if the point is invalid 00620 if (!pcl_isfinite (data_->points[cp].x) || 00621 !pcl_isfinite (data_->points[cp].y) || 00622 !pcl_isfinite (data_->points[cp].z)) 00623 continue; 00624 00625 Eigen::Vector3i index_3d; 00626 getCellIndex (data_->points[cp].getVector4fMap (), index_3d); 00627 int index_1d = getIndexIn1D (index_3d); 00628 if (cell_hash_map_.find (index_1d) == cell_hash_map_.end ()) 00629 { 00630 Leaf cell_data; 00631 cell_data.data_indices.push_back (cp); 00632 getCellCenterFromIndex (index_3d, cell_data.pt_on_surface); 00633 cell_hash_map_[index_1d] = cell_data; 00634 occupied_cell_list_[index_1d] = 1; 00635 } 00636 else 00637 { 00638 Leaf cell_data = cell_hash_map_.at (index_1d); 00639 cell_data.data_indices.push_back (cp); 00640 cell_hash_map_[index_1d] = cell_data; 00641 } 00642 } 00643 00644 Eigen::Vector3i index; 00645 int numOfFilledPad = 0; 00646 00647 for (int i = 0; i < data_size_; ++i) 00648 { 00649 for (int j = 0; j < data_size_; ++j) 00650 { 00651 for (int k = 0; k < data_size_; ++k) 00652 { 00653 index[0] = i; 00654 index[1] = j; 00655 index[2] = k; 00656 if (occupied_cell_list_[getIndexIn1D (index)]) 00657 { 00658 fillPad (index); 00659 numOfFilledPad++; 00660 } 00661 } 00662 } 00663 } 00664 00665 // Update the hashtable and store the vector and point 00666 BOOST_FOREACH (typename HashMap::value_type entry, cell_hash_map_) 00667 { 00668 getIndexIn3D (entry.first, index); 00669 std::vector <int> pt_union_indices; 00670 getDataPtsUnion (index, pt_union_indices); 00671 00672 // Needs at least 10 points (?) 00673 // NOTE: set as parameter later 00674 if (pt_union_indices.size () > 10) 00675 { 00676 storeVectAndSurfacePoint (entry.first, index, pt_union_indices, entry.second); 00677 //storeVectAndSurfacePointKNN(entry.first, index, entry.second); 00678 occupied_cell_list_[entry.first] = 1; 00679 } 00680 } 00681 00682 // Go through the hash table another time to extract surface 00683 BOOST_FOREACH (typename HashMap::value_type entry, cell_hash_map_) 00684 { 00685 getIndexIn3D (entry.first, index); 00686 std::vector <int> pt_union_indices; 00687 getDataPtsUnion (index, pt_union_indices); 00688 00689 // Needs at least 10 points (?) 00690 // NOTE: set as parameter later 00691 if (pt_union_indices.size () > 10) 00692 createSurfaceForCell (index, pt_union_indices); 00693 } 00694 00695 polygons.resize (surface_.size () / 4); 00696 // Copy the data from surface_ to polygons 00697 for (size_t i = 0; i < polygons.size (); ++i) 00698 { 00699 pcl::Vertices v; 00700 v.vertices.resize (4); 00701 for (int j = 0; j < 4; ++j) 00702 v.vertices[j] = i*4+j; 00703 polygons[i] = v; 00704 } 00705 return (true); 00706 } 00707 00709 template <typename PointNT> void 00710 pcl::GridProjection<PointNT>::performReconstruction (pcl::PolygonMesh &output) 00711 { 00712 if (!reconstructPolygons (output.polygons)) 00713 return; 00714 00715 // The mesh surface is held in surface_. Copy it to the output format 00716 output.header = input_->header; 00717 00718 pcl::PointCloud<pcl::PointXYZ> cloud; 00719 cloud.width = surface_.size (); 00720 cloud.height = 1; 00721 cloud.is_dense = true; 00722 00723 cloud.points.resize (surface_.size ()); 00724 // Copy the data from surface_ to cloud 00725 for (size_t i = 0; i < cloud.points.size (); ++i) 00726 { 00727 cloud.points[i].x = surface_[i].x (); 00728 cloud.points[i].y = surface_[i].y (); 00729 cloud.points[i].z = surface_[i].z (); 00730 } 00731 pcl::toROSMsg (cloud, output.cloud); 00732 } 00733 00735 template <typename PointNT> void 00736 pcl::GridProjection<PointNT>::performReconstruction (pcl::PointCloud<PointNT> &points, 00737 std::vector<pcl::Vertices> &polygons) 00738 { 00739 if (!reconstructPolygons (polygons)) 00740 return; 00741 00742 // The mesh surface is held in surface_. Copy it to the output format 00743 points.header = input_->header; 00744 points.width = surface_.size (); 00745 points.height = 1; 00746 points.is_dense = true; 00747 00748 points.resize (surface_.size ()); 00749 // Copy the data from surface_ to cloud 00750 for (size_t i = 0; i < points.size (); ++i) 00751 { 00752 points[i].x = surface_[i].x (); 00753 points[i].y = surface_[i].y (); 00754 points[i].z = surface_[i].z (); 00755 } 00756 } 00757 00758 #define PCL_INSTANTIATE_GridProjection(T) template class PCL_EXPORTS pcl::GridProjection<T>; 00759 00760 #endif // PCL_SURFACE_IMPL_GRID_PROJECTION_H_ 00761
1.8.0