00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
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/vector_average.h>
00044 #include <pcl/features/normal_3d.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)
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)
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 }
00068
00070 template <typename PointNT> void
00071 pcl::GridProjection<PointNT>::scaleInputDataPoint (double scale_factor)
00072 {
00073 for (size_t i = 0; i < data_->points.size(); ++i)
00074 data_->points[i].getVector4fMap () /= scale_factor;
00075 max_p_ /= scale_factor;
00076 min_p_ /= scale_factor;
00077 }
00078
00080 template <typename PointNT> void
00081 pcl::GridProjection<PointNT>::getBoundingBox ()
00082 {
00083 pcl::getMinMax3D (*data_, min_p_, max_p_);
00084
00085 Eigen::Vector4f bounding_box_size = max_p_ - min_p_;
00086 double scale_factor = (std::max)((std::max)(bounding_box_size.x (),
00087 bounding_box_size.y ()),
00088 bounding_box_size.z ());
00089 if (scale_factor > 1)
00090 scaleInputDataPoint (scale_factor);
00091
00092
00093 int upper_right_index[3];
00094 int lower_left_index[3];
00095 for (size_t i = 0; i < 3; ++i)
00096 {
00097 upper_right_index[i] = max_p_(i) / leaf_size_ + 5;
00098 lower_left_index[i] = min_p_(i) / leaf_size_ - 5;
00099 max_p_(i) = upper_right_index[i] * leaf_size_;
00100 min_p_(i) = lower_left_index[i] * leaf_size_;
00101 }
00102 bounding_box_size = max_p_ - min_p_;
00103 ROS_DEBUG ("[pcl::GridProjection::getBoundingBox] Size of Bounding Box is [%f, %f, %f]",
00104 bounding_box_size.x (), bounding_box_size.y (), bounding_box_size.z ());
00105 double max_size =
00106 (std::max) ((std::max)(bounding_box_size.x (), bounding_box_size.y ()),
00107 bounding_box_size.z ());
00108
00109 data_size_ = max_size / leaf_size_;
00110 ROS_DEBUG ("[pcl::GridProjection::getBoundingBox] Lower left point is [%f, %f, %f]",
00111 min_p_.x (), min_p_.y (), min_p_.z ());
00112 ROS_DEBUG ("[pcl::GridProjection::getBoundingBox] Upper left point is [%f, %f, %f]",
00113 max_p_.x (), max_p_.y (), max_p_.z ());
00114 ROS_DEBUG ("[pcl::GridProjection::getBoundingBox] Padding size: %d", padding_size_);
00115 ROS_DEBUG ("[pcl::GridProjection::getBoundingBox] Leaf size: %f", leaf_size_);
00116 occupied_cell_list_.resize (data_size_ * data_size_ * data_size_);
00117 gaussian_scale_ = pow ((padding_size_+1) * leaf_size_ / 2.0, 2.0);
00118 }
00119
00121 template <typename PointNT> void
00122 pcl::GridProjection<PointNT>::getVertexFromCellCenter(const Eigen::Vector4f &cell_center,
00123 Eigen::Vector4f (&pts)[8]) const
00124 {
00125 float sz = leaf_size_ / 2.0;
00126
00127 pts[0] = cell_center + Eigen::Vector4f (-sz, sz, -sz, 0);
00128 pts[1] = cell_center + Eigen::Vector4f (-sz, -sz, -sz, 0);
00129 pts[2] = cell_center + Eigen::Vector4f (sz, -sz, -sz, 0);
00130 pts[3] = cell_center + Eigen::Vector4f (sz, sz, -sz, 0);
00131 pts[4] = cell_center + Eigen::Vector4f (-sz, sz, sz, 0);
00132 pts[5] = cell_center + Eigen::Vector4f (-sz, -sz, sz, 0);
00133 pts[6] = cell_center + Eigen::Vector4f (sz, -sz, sz, 0);
00134 pts[7] = cell_center + Eigen::Vector4f (sz, sz, sz, 0);
00135 }
00136
00138 template <typename PointNT> void
00139 pcl::GridProjection<PointNT>::getVertexFromIndex (const Index3D &index,
00140 Eigen::Vector4f (&pts)[8]) const
00141 {
00142 Eigen::Vector4f cell_center;
00143 getCellCenterFromIndex (index, cell_center);
00144 getVertexFromCellCenter (cell_center, pts);
00145 }
00146
00148 template <typename PointNT> void
00149 pcl::GridProjection<PointNT>::getDataPtsUnion (const Index3D &index,
00150 std::vector <int> &pt_union_indices)
00151 {
00152 for (int i = index[0] - padding_size_; i <= index[0] + padding_size_; ++i)
00153 {
00154 for (int j = index[1] - padding_size_; j <= index[1] + padding_size_; ++j)
00155 {
00156 for (int k = index[2] - padding_size_; k <= index[2] + padding_size_; ++k)
00157 {
00158 Index3D cell_index_3d = { i, j, k };
00159 int cell_index_1d = getIndexIn1D (cell_index_3d);
00160 if (cell_hash_map_.find (cell_index_1d) != cell_hash_map_.end ())
00161 {
00162
00163
00164 pt_union_indices.insert (pt_union_indices.end (),
00165 cell_hash_map_.at (cell_index_1d).data_indices.begin (),
00166 cell_hash_map_.at (cell_index_1d).data_indices.end ());
00167 }
00168 }
00169 }
00170 }
00171 }
00172
00174 template <typename PointNT> void
00175 pcl::GridProjection<PointNT>::createSurfaceForCell (const Index3D &index,
00176 std::vector <int> &pt_union_indices)
00177 {
00178
00179 Eigen::Vector4f vertices[8];
00180
00181
00182 Eigen::Vector4f pts[4];
00183 vector3d vector_at_pts[4];
00184
00185 getVertexFromIndex (index, vertices);
00186
00187
00188 Index3D indices[4] = { {index[0], index[1], index[2] - 1},
00189 {index[0], index[1], index[2]},
00190 {index[0], index[1] - 1, index[2]},
00191 {index[0] + 1, index[1], index[2]} };
00192
00193
00194 for (size_t i = 0; i < 4; ++i)
00195 {
00196 pts[i] = vertices[I_SHIFT_PT[i]];
00197 unsigned int index_1d = getIndexIn1D (indices[i]);
00198 if (cell_hash_map_.find (index_1d) == cell_hash_map_.end () ||
00199 occupied_cell_list_[index_1d] == 0)
00200 return;
00201 else
00202 vector_at_pts[i] = cell_hash_map_.at (index_1d).vect_at_grid_pt;
00203 }
00204
00205
00206 for (size_t i = 0; i < 3; ++i)
00207 {
00208 Eigen::Vector4f end_pts[2];
00209 vector3d vect_at_end_pts[2];
00210 for (size_t j = 0; j < 2; ++j)
00211 {
00212 end_pts[j] = pts[I_SHIFT_EDGE[i][j]];
00213 vect_at_end_pts[j] = vector_at_pts[I_SHIFT_EDGE[i][j]];
00214 }
00215 if (isIntersected (end_pts, vect_at_end_pts, pt_union_indices))
00216 {
00217
00218
00219 Index3D polygon[4];
00220 Eigen::Vector4f polygon_pts[4];
00221 int polygon_indices_1d[4];
00222 bool is_all_in_hash_map = true;
00223 switch (i)
00224 {
00225 case 0:
00226 polygon[0][0] = index[0] - 1;
00227 polygon[0][1] = index[1] + 1;
00228 polygon[0][2] = index[2];
00229
00230 polygon[1][0] = index[0] - 1;
00231 polygon[1][1] = index[1];
00232 polygon[1][2] = index[2];
00233
00234 polygon[2][0] = index[0];
00235 polygon[2][1] = index[1];
00236 polygon[2][2] = index[2];
00237
00238 polygon[3][0] = index[0];
00239 polygon[3][1] = index[1] + 1;
00240 polygon[3][2] = index[2];
00241 break;
00242 case 1:
00243 polygon[0][0] = index[0];
00244 polygon[0][1] = index[1] + 1;
00245 polygon[0][2] = index[2] + 1;
00246
00247 polygon[1][0] = index[0];
00248 polygon[1][1] = index[1] + 1;
00249 polygon[1][2] = index[2];
00250
00251 polygon[2][0] = index[0];
00252 polygon[2][1] = index[1];
00253 polygon[2][2] = index[2];
00254
00255 polygon[3][0] = index[0];
00256 polygon[3][1] = index[1];
00257 polygon[3][2] = index[2] + 1;
00258 break;
00259 case 2:
00260 polygon[0][0] = index[0] - 1;
00261 polygon[0][1] = index[1];
00262 polygon[0][2] = index[2] + 1;
00263
00264 polygon[1][0] = index[0] - 1;
00265 polygon[1][1] = index[1];
00266 polygon[1][2] = index[2];
00267
00268 polygon[2][0] = index[0];
00269 polygon[2][1] = index[1];
00270 polygon[2][2] = index[2];
00271
00272 polygon[3][0] = index[0];
00273 polygon[3][1] = index[1];
00274 polygon[3][2] = index[2] + 1;
00275 break;
00276 default:
00277 break;
00278 }
00279 for (size_t k = 0; k < 4; k++)
00280 {
00281 polygon_indices_1d[k] = getIndexIn1D (polygon[k]);
00282 if (!occupied_cell_list_[polygon_indices_1d[k]])
00283 {
00284 is_all_in_hash_map = false;
00285 break;
00286 }
00287 }
00288 if (is_all_in_hash_map)
00289 {
00290 for (size_t k = 0; k < 4; k++)
00291 {
00292 polygon_pts[k] = cell_hash_map_.at (polygon_indices_1d[k]).pt_on_surface;
00293 surface_.push_back (polygon_pts[k]);
00294 }
00295 }
00296 }
00297 }
00298 }
00299
00301 template <typename PointNT> Eigen::Vector4f
00302 pcl::GridProjection<PointNT>::getProjection (const Eigen::Vector4f &p,
00303 std::vector <int> &pt_union_indices)
00304 {
00305 const double projection_distance = leaf_size_ * 3;
00306 Eigen::Vector4f end_pt[2];
00307 vector3d end_pt_vect[2];
00308 end_pt[0] = p;
00309 end_pt_vect[0] = getVectorAtPoint (end_pt[0], pt_union_indices);
00310 end_pt_vect[0].normalize();
00311
00312 double dSecond = getD2AtPoint (end_pt[0], end_pt_vect[0], pt_union_indices);
00313
00314
00315
00316
00317 if (dSecond > 0)
00318 end_pt[1] = end_pt[0] + Eigen::Vector4f (end_pt_vect[0][0] * projection_distance,
00319 end_pt_vect[0][1] * projection_distance,
00320 end_pt_vect[0][2] * projection_distance, 0);
00321 else
00322 end_pt[1] = end_pt[0] - Eigen::Vector4f (end_pt_vect[0][0] * projection_distance,
00323 end_pt_vect[0][1] * projection_distance,
00324 end_pt_vect[0][2] * projection_distance, 0);
00325 end_pt_vect[1] = getVectorAtPoint (end_pt[1], pt_union_indices);
00326 if (end_pt_vect[1].dot (end_pt_vect[0]) < 0)
00327 {
00328 Eigen::Vector4f mid_pt = end_pt[0] + (end_pt[1] - end_pt[0]) * 0.5;
00329 return (findIntersection (0, end_pt, end_pt_vect, mid_pt, pt_union_indices));
00330 }
00331 return (p);
00332 }
00333
00335 template <typename PointNT> Eigen::Vector4f
00336 pcl::GridProjection<PointNT>::getProjectionWithPlaneFit (const Eigen::Vector4f &p,
00337 std::vector <int> (&pt_union_indices))
00338 {
00339
00340 Eigen::Vector4f model_coefficients;
00341 float curvature;
00343 pcl::computePointNormal (*data_, pt_union_indices, model_coefficients, curvature);
00344
00345
00346 Eigen::Vector3f point (p.x (), p.y (), p.z ());
00347 float distance = point.dot (model_coefficients.head < 3 > ()) + model_coefficients[3];
00348 point -= distance * model_coefficients.head < 3 > ();
00349
00350 return (Eigen::Vector4f (point[0], point[1], point[2], 0));
00351
00352
00353
00354 }
00355
00357 template <typename PointNT> Eigen::Vector3f
00358 pcl::GridProjection<PointNT>::getVectorAtPoint (const Eigen::Vector4f &p,
00359 std::vector <int> &pt_union_indices)
00360 {
00361 std::vector <double> pt_union_dist (pt_union_indices.size ());
00362 std::vector <double> pt_union_weight (pt_union_indices.size ());
00363 vector3d out_vector (0, 0, 0);
00364 double sum = 0.0;
00365 double mag = 0.0;
00366
00367 for (size_t i = 0; i < pt_union_indices.size (); ++i)
00368 {
00369 pt_union_dist[i] = (data_->points[pt_union_indices[i]].getVector4fMap () - p).squaredNorm ();
00370 pt_union_weight[i] = pow (M_E, -pow (pt_union_dist[i], 2.0) / gaussian_scale_);
00371 mag += pow (M_E, -pow (sqrt (pt_union_dist[i]), 2.0) / gaussian_scale_);
00372 sum += pt_union_weight[i];
00373 }
00374
00375 pcl::VectorAverage3f vector_average;
00376
00377 vector3d v (data_->points[pt_union_indices[0]].normal[0],
00378 data_->points[pt_union_indices[0]].normal[1],
00379 data_->points[pt_union_indices[0]].normal[2]);
00380
00381 for (size_t i = 0; i < pt_union_weight.size (); ++i)
00382 {
00383 pt_union_weight[i] /= sum;
00384 vector3d vec (data_->points[pt_union_indices[i]].normal[0],
00385 data_->points[pt_union_indices[i]].normal[1],
00386 data_->points[pt_union_indices[i]].normal[2]);
00387 if (vec.dot (v) < 0)
00388 vec = -vec;
00389 vector_average.add (vec, pt_union_weight[i]);
00390 }
00391 out_vector = vector_average.getMean ();
00392
00393
00394 out_vector.normalize ();
00395 double d1 = getD1AtPoint (p, out_vector, pt_union_indices);
00396 out_vector = out_vector * sum;
00397 return ((d1 > 0) ? -1 : 1) * out_vector;
00398 }
00399
00401 template <typename PointNT> Eigen::Vector3f
00402 pcl::GridProjection<PointNT>::getVectorAtPointKNN (const Eigen::Vector4f &p,
00403 std::vector <int> &k_indices,
00404 std::vector <float> &k_squared_distances)
00405 {
00406 vector3d out_vector (0, 0, 0);
00407 std::vector <float> k_weight;
00408 k_weight.resize (k_);
00409 float sum = 0.0;
00410 for (int i = 0; i < k_; i++)
00411 {
00412 k_weight[i] = pow (M_E, -pow (k_squared_distances[i], 2.0) / gaussian_scale_);
00413 sum += k_weight[i];
00414 }
00415 pcl::VectorAverage3f vector_average;
00416 for (int i = 0; i < k_; i++)
00417 {
00418 k_weight[i] /= sum;
00419 vector3d vec (data_->points[k_indices[i]].normal[0],
00420 data_->points[k_indices[i]].normal[1],
00421 data_->points[k_indices[i]].normal[2]);
00422 vector_average.add (vec, k_weight[i]);
00423 }
00424 vector_average.getEigenVector1 (out_vector);
00425 out_vector.normalize ();
00426 double d1 = getD1AtPoint (p, out_vector, k_indices);
00427 out_vector = out_vector * sum;
00428 return ((d1 > 0) ? -1 : 1) * out_vector;
00429
00430 }
00431
00433 template <typename PointNT> double
00434 pcl::GridProjection<PointNT>::getMagAtPoint (const Eigen::Vector4f &p,
00435 const std::vector <int> &pt_union_indices)
00436 {
00437 std::vector <double> pt_union_dist (pt_union_indices.size ());
00438 std::vector <double> pt_union_weight (pt_union_indices.size ());
00439 vector3d out_vector;
00440 double sum = 0.0;
00441 for (size_t i = 0; i < pt_union_indices.size (); ++i)
00442 {
00443 pt_union_dist[i] = (data_->points[pt_union_indices[i]].getVector4fMap () - p).norm ();
00444 sum += pow (M_E, -pow (pt_union_dist[i], 2.0) / gaussian_scale_);
00445 }
00446 return (sum);
00447 }
00448
00450 template <typename PointNT> double
00451 pcl::GridProjection<PointNT>::getD1AtPoint (const Eigen::Vector4f &p, const vector3d &vec,
00452 const std::vector <int> &pt_union_indices)
00453 {
00454 double sz = 0.01 * leaf_size_;
00455 vector3d v = vec * sz;
00456
00457 double forward = getMagAtPoint (p + Eigen::Vector4f (v[0], v[1], v[2], 0), pt_union_indices);
00458 double backward = getMagAtPoint (p - Eigen::Vector4f (v[0], v[1], v[2], 0), pt_union_indices);
00459 return ((forward - backward) / (0.02 * leaf_size_));
00460 }
00461
00463 template <typename PointNT> double
00464 pcl::GridProjection<PointNT>::getD2AtPoint (const Eigen::Vector4f &p, const vector3d &vec,
00465 const std::vector <int> &pt_union_indices)
00466 {
00467 double sz = 0.01 * leaf_size_;
00468 vector3d v = vec * sz;
00469
00470 double forward = getD1AtPoint (p + Eigen::Vector4f (v[0], v[1], v[2], 0), vec, pt_union_indices);
00471 double backward = getD1AtPoint (p - Eigen::Vector4f (v[0], v[1], v[2], 0), vec, pt_union_indices);
00472 return ((forward - backward) / (0.02 * leaf_size_));
00473 }
00474
00476 template <typename PointNT> bool
00477 pcl::GridProjection<PointNT>::isIntersected (const Eigen::Vector4f (&end_pts)[2],
00478 vector3d vect_at_end_pts[2],
00479 std::vector <int> &pt_union_indices)
00480 {
00481 double length[2];
00482 for (size_t i = 0; i < 2; ++i)
00483 {
00484 length[i] = vect_at_end_pts[i].norm ();
00485 vect_at_end_pts[i].normalize ();
00486 }
00487 double dot_prod = vect_at_end_pts[0].dot (vect_at_end_pts[1]);
00488 if (dot_prod < 0)
00489 {
00490 double ratio = length[0] / (length[0] + length[1]);
00491 Eigen::Vector4f start_pt = end_pts[0] + (end_pts[1] - end_pts[0]) * ratio;
00492 Eigen::Vector4f intersection_pt = findIntersection (0, end_pts, vect_at_end_pts, start_pt, pt_union_indices);
00493
00494 vector3d vec = getVectorAtPoint (intersection_pt, pt_union_indices);
00495 vec.normalize ();
00496
00497 double d2 = getD2AtPoint (intersection_pt, vec, pt_union_indices);
00498 if (d2 < 0)
00499 return (true);
00500 }
00501 return (false);
00502 }
00503
00505 template <typename PointNT> Eigen::Vector4f
00506 pcl::GridProjection<PointNT>::findIntersection (int level,
00507 const Eigen::Vector4f (&end_pts)[2],
00508 vector3d vect_at_end_pts[2],
00509 const Eigen::Vector4f &start_pt,
00510 std::vector <int> &pt_union_indices)
00511 {
00512 vector3d vec = getVectorAtPoint (start_pt, pt_union_indices);
00513 double d1 = getD1AtPoint (start_pt, vec, pt_union_indices);
00514 Eigen::Vector4f new_end_pts[2];
00515 vector3d new_vect_at_end_pts[2];
00516 if ((abs (d1) < 10e-3) || (level == max_binary_search_level_))
00517 {
00518 return (start_pt);
00519 }
00520 else
00521 {
00522 vec.normalize ();
00523 if (vec.dot (vect_at_end_pts[0]) < 0)
00524 {
00525 Eigen::Vector4f new_start_pt = end_pts[0] + (start_pt - end_pts[0]) * 0.5;
00526 new_end_pts[0] = end_pts[0];
00527 new_end_pts[1] = start_pt;
00528 new_vect_at_end_pts[0] = vect_at_end_pts[0];
00529 new_vect_at_end_pts[1] = vec;
00530 return (findIntersection (level + 1, new_end_pts, new_vect_at_end_pts, new_start_pt, pt_union_indices));
00531 }
00532 if (vec.dot (vect_at_end_pts[1]) < 0)
00533 {
00534 Eigen::Vector4f new_start_pt = start_pt + (end_pts[1] - start_pt) * 0.5;
00535 new_end_pts[0] = start_pt;
00536 new_end_pts[1] = end_pts[1];
00537 new_vect_at_end_pts[0] = vec;
00538 new_vect_at_end_pts[1] = vect_at_end_pts[1];
00539 return (findIntersection (level + 1, new_end_pts, new_vect_at_end_pts, new_start_pt, pt_union_indices));
00540 }
00541 return (start_pt);
00542 }
00543 }
00544
00545
00547 template <typename PointNT> void
00548 pcl::GridProjection<PointNT>::fillPad (const Index3D &index)
00549 {
00550 for (int i = index[0] - padding_size_; i < index[0] + padding_size_; ++i)
00551 {
00552 for (int j = index[1] - padding_size_; j < index[1] + padding_size_; ++j)
00553 {
00554 for (int k = index[2] - padding_size_; k < index[2] + padding_size_; ++k)
00555 {
00556 Index3D cell_index_3d = { i, j, k };
00557 unsigned int cell_index_1d = getIndexIn1D (cell_index_3d);
00558 if (cell_hash_map_.find (cell_index_1d) == cell_hash_map_.end ())
00559 {
00560 cell_hash_map_[cell_index_1d].data_indices.resize (0);
00561 getCellCenterFromIndex (cell_index_3d, cell_hash_map_[cell_index_1d].pt_on_surface);
00562 }
00563 }
00564 }
00565 }
00566 }
00567
00568
00570 template <typename PointNT> void
00571 pcl::GridProjection<PointNT>::storeVectAndSurfacePoint (int index_1d,
00572 const Index3D &index_3d,
00573 std::vector <int> &pt_union_indices,
00574 const Leaf &cell_data)
00575 {
00576
00577 Eigen::Vector4f grid_pt (cell_data.pt_on_surface.x () - leaf_size_ / 2.0,
00578 cell_data.pt_on_surface.y () + leaf_size_ / 2.0,
00579 cell_data.pt_on_surface.z () + leaf_size_ / 2.0, 0);
00580
00581
00582 cell_hash_map_[index_1d].vect_at_grid_pt = getVectorAtPoint (grid_pt, pt_union_indices);
00583 cell_hash_map_[index_1d].pt_on_surface = getProjection (cell_data.pt_on_surface, pt_union_indices);
00584 }
00585
00587 template <typename PointNT> void
00588 pcl::GridProjection<PointNT>::storeVectAndSurfacePointKNN (int index_1d, Index3D index_3d,
00589 Leaf cell_data)
00590 {
00591 Eigen::Vector4f cell_center = cell_data.pt_on_surface;
00592 Eigen::Vector4f grid_pt (cell_center.x () - leaf_size_ / 2,
00593 cell_center.y () + leaf_size_ / 2,
00594 cell_center.z () + leaf_size_ / 2, 0);
00595
00596 std::vector <int> k_indices;
00597 k_indices.resize (k_);
00598 std::vector <float> k_squared_distances;
00599 k_squared_distances.resize (k_);
00600
00601 PointNT pt; pt.x = grid_pt.x (); pt.y = grid_pt.y (); pt.z = grid_pt.z ();
00602 tree_->nearestKSearch (pt, k_, k_indices, k_squared_distances);
00603
00604 cell_data.vect_at_grid_pt = getVectorAtPointKNN (grid_pt, k_indices, k_squared_distances);
00605 cell_data.pt_on_surface = getProjectionWithPlaneFit (cell_center, k_indices);
00606 cell_hash_map_[index_1d] = cell_data;
00607 }
00608
00610 template <typename PointNT> void
00611 pcl::GridProjection<PointNT>::performReconstruction (pcl::PolygonMesh &output)
00612 {
00613 data_.reset (new pcl::PointCloud<PointNT> (*input_));
00614 getBoundingBox ();
00615
00616
00617
00618 cell_hash_map_.max_load_factor (2.0);
00619 cell_hash_map_.rehash (data_->points.size () / cell_hash_map_.max_load_factor ());
00620
00621
00622 for (size_t cp = 0; cp < data_->points.size (); ++cp)
00623 {
00624
00625 if (!pcl_isfinite (data_->points[cp].x) ||
00626 !pcl_isfinite (data_->points[cp].y) ||
00627 !pcl_isfinite (data_->points[cp].z))
00628 continue;
00629
00630 Index3D index_3d;
00631 getCellIndex (data_->points[cp].getVector4fMap (), index_3d);
00632 int index_1d = getIndexIn1D (index_3d);
00633 if (cell_hash_map_.find (index_1d) == cell_hash_map_.end ())
00634 {
00635 Leaf cell_data;
00636 cell_data.data_indices.push_back (cp);
00637 getCellCenterFromIndex (index_3d, cell_data.pt_on_surface);
00638 cell_hash_map_[index_1d] = cell_data;
00639 occupied_cell_list_[index_1d] = 1;
00640 }
00641 else
00642 {
00643 Leaf cell_data = cell_hash_map_.at (index_1d);
00644 cell_data.data_indices.push_back (cp);
00645 cell_hash_map_[index_1d] = cell_data;
00646 }
00647 }
00648
00649 Index3D index;
00650 int numOfFilledPad = 0;
00651
00652 for (int i = 0; i < data_size_; ++i)
00653 {
00654 for (int j = 0; j < data_size_; ++j)
00655 {
00656 for (int k = 0; k < data_size_; ++k)
00657 {
00658 index[0] = i;
00659 index[1] = j;
00660 index[2] = k;
00661 if (occupied_cell_list_[getIndexIn1D (index)])
00662 {
00663 fillPad (index);
00664 numOfFilledPad++;
00665 }
00666 }
00667 }
00668 }
00669
00670
00671 BOOST_FOREACH (typename HashMap::value_type entry, cell_hash_map_)
00672 {
00673 getIndexIn3D (entry.first, index);
00674 std::vector <int> pt_union_indices;
00675 getDataPtsUnion (index, pt_union_indices);
00676
00677
00678
00679 if (pt_union_indices.size () > 10)
00680 {
00681 storeVectAndSurfacePoint (entry.first, index, pt_union_indices, entry.second);
00682
00683 occupied_cell_list_[entry.first] = 1;
00684 }
00685 }
00686
00687
00688 BOOST_FOREACH (typename HashMap::value_type entry, cell_hash_map_)
00689 {
00690 getIndexIn3D (entry.first, index);
00691 std::vector <int> pt_union_indices;
00692 getDataPtsUnion (index, pt_union_indices);
00693
00694
00695
00696 if (pt_union_indices.size () > 10)
00697 createSurfaceForCell (index, pt_union_indices);
00698 }
00699
00700
00701 output.header = input_->header;
00702
00703 PointCloud<pcl::PointXYZ> cloud;
00704 cloud.width = surface_.size ();
00705 cloud.height = 1;
00706 cloud.is_dense = true;
00707
00708 cloud.points.resize (surface_.size ());
00709
00710 for (size_t i = 0; i < cloud.points.size (); ++i)
00711 {
00712 cloud.points[i].x = surface_[i].x ();
00713 cloud.points[i].y = surface_[i].y ();
00714 cloud.points[i].z = surface_[i].z ();
00715 }
00716 pcl::toROSMsg (cloud, output.cloud);
00717
00718 output.polygons.resize (surface_.size () / 4);
00719
00720 for (size_t i = 0; i < output.polygons.size (); ++i)
00721 {
00722 pcl::Vertices v;
00723 v.vertices.resize (4);
00724 for (int j = 0; j < 4; ++j)
00725 v.vertices[j] = i*4+j;
00726 output.polygons[i] = v;
00727 }
00728 }
00729
00730 #define PCL_INSTANTIATE_GridProjection(T) template class pcl::GridProjection<T>;
00731
00732 #endif // PCL_SURFACE_IMPL_GRID_PROJECTION_H_
00733