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
00039
00040 #ifndef PCL_SURFACE_IMPL_MLS_H_
00041 #define PCL_SURFACE_IMPL_MLS_H_
00042
00043 #include <pcl/point_traits.h>
00044 #include <pcl/surface/mls.h>
00045 #include <pcl/common/io.h>
00046 #include <pcl/common/centroid.h>
00047 #include <pcl/common/eigen.h>
00048 #include <pcl/common/geometry.h>
00049
00050 #ifdef _OPENMP
00051 #include <omp.h>
00052 #endif
00053
00055 template <typename PointInT, typename PointOutT> void
00056 pcl::MovingLeastSquares<PointInT, PointOutT>::process (PointCloudOut &output)
00057 {
00058
00059 corresponding_input_indices_.reset (new PointIndices);
00060
00061
00062 if (compute_normals_)
00063 {
00064 normals_.reset (new NormalCloud);
00065
00066 normals_->header = input_->header;
00067
00068 normals_->width = normals_->height = 0;
00069 normals_->points.clear ();
00070 }
00071
00072
00073
00074 output.header = input_->header;
00075 output.width = output.height = 0;
00076 output.points.clear ();
00077
00078 if (search_radius_ <= 0 || sqr_gauss_param_ <= 0)
00079 {
00080 PCL_ERROR ("[pcl::%s::process] Invalid search radius (%f) or Gaussian parameter (%f)!\n", getClassName ().c_str (), search_radius_, sqr_gauss_param_);
00081 return;
00082 }
00083
00084
00085 if (upsample_method_ == DISTINCT_CLOUD && !distinct_cloud_)
00086 {
00087 PCL_ERROR ("[pcl::%s::process] Upsample method was set to DISTINCT_CLOUD, but no distinct cloud was specified.\n", getClassName ().c_str ());
00088 return;
00089 }
00090
00091 if (!initCompute ())
00092 return;
00093
00094
00095
00096 if (!tree_)
00097 {
00098 KdTreePtr tree;
00099 if (input_->isOrganized ())
00100 tree.reset (new pcl::search::OrganizedNeighbor<PointInT> ());
00101 else
00102 tree.reset (new pcl::search::KdTree<PointInT> (false));
00103 setSearchMethod (tree);
00104 }
00105
00106
00107 tree_->setInputCloud (input_);
00108
00109 switch (upsample_method_)
00110 {
00111
00112 case (RANDOM_UNIFORM_DENSITY):
00113 {
00114 rng_alg_.seed (static_cast<unsigned> (std::time (0)));
00115 float tmp = static_cast<float> (search_radius_ / 2.0f);
00116 boost::uniform_real<float> uniform_distrib (-tmp, tmp);
00117 rng_uniform_distribution_.reset (new boost::variate_generator<boost::mt19937&, boost::uniform_real<float> > (rng_alg_, uniform_distrib));
00118
00119 break;
00120 }
00121 case (VOXEL_GRID_DILATION):
00122 case (DISTINCT_CLOUD):
00123 {
00124 mls_results_.resize (input_->size ());
00125 break;
00126 }
00127 default:
00128 break;
00129 }
00130
00131
00132 performProcessing (output);
00133
00134 if (compute_normals_)
00135 {
00136 normals_->height = 1;
00137 normals_->width = static_cast<uint32_t> (normals_->size ());
00138
00139 for (unsigned int i = 0; i < output.size (); ++i)
00140 {
00141 typedef typename pcl::traits::fieldList<PointOutT>::type FieldList;
00142 pcl::for_each_type<FieldList> (SetIfFieldExists<PointOutT, float> (output.points[i], "normal_x", normals_->points[i].normal_x));
00143 pcl::for_each_type<FieldList> (SetIfFieldExists<PointOutT, float> (output.points[i], "normal_y", normals_->points[i].normal_y));
00144 pcl::for_each_type<FieldList> (SetIfFieldExists<PointOutT, float> (output.points[i], "normal_z", normals_->points[i].normal_z));
00145 pcl::for_each_type<FieldList> (SetIfFieldExists<PointOutT, float> (output.points[i], "curvature", normals_->points[i].curvature));
00146 }
00147
00148 }
00149
00150
00151 output.height = 1;
00152 output.width = static_cast<uint32_t> (output.size ());
00153
00154 deinitCompute ();
00155 }
00156
00158 template <typename PointInT, typename PointOutT> void
00159 pcl::MovingLeastSquares<PointInT, PointOutT>::computeMLSPointNormal (int index,
00160 const std::vector<int> &nn_indices,
00161 std::vector<float> &nn_sqr_dists,
00162 PointCloudOut &projected_points,
00163 NormalCloud &projected_points_normals,
00164 PointIndices &corresponding_input_indices,
00165 MLSResult &mls_result) const
00166 {
00167
00168
00169
00170
00171 EIGEN_ALIGN16 Eigen::Matrix3d covariance_matrix;
00172 Eigen::Vector4d xyz_centroid;
00173
00174
00175 pcl::compute3DCentroid (*input_, nn_indices, xyz_centroid);
00176
00177
00178 pcl::computeCovarianceMatrix (*input_, nn_indices, xyz_centroid, covariance_matrix);
00179 EIGEN_ALIGN16 Eigen::Vector3d::Scalar eigen_value;
00180 EIGEN_ALIGN16 Eigen::Vector3d eigen_vector;
00181 Eigen::Vector4d model_coefficients;
00182 pcl::eigen33 (covariance_matrix, eigen_value, eigen_vector);
00183 model_coefficients.head<3> ().matrix () = eigen_vector;
00184 model_coefficients[3] = 0;
00185 model_coefficients[3] = -1 * model_coefficients.dot (xyz_centroid);
00186
00187
00188 Eigen::Vector3d point = input_->points[index].getVector3fMap ().template cast<double> ();
00189 double distance = point.dot (model_coefficients.head<3> ()) + model_coefficients[3];
00190 point -= distance * model_coefficients.head<3> ();
00191
00192 float curvature = static_cast<float> (covariance_matrix.trace ());
00193
00194 if (curvature != 0)
00195 curvature = fabsf (float (eigen_value / double (curvature)));
00196
00197
00198
00199 Eigen::Vector3d plane_normal = model_coefficients.head<3> ();
00200
00201 Eigen::VectorXd c_vec;
00202
00203 Eigen::Vector3d v_axis (0.0f, 0.0f, 0.0f), u_axis (0.0f, 0.0f, 0.0f);
00204
00205
00206
00207
00209 if (polynomial_fit_ && static_cast<int> (nn_indices.size ()) >= nr_coeff_)
00210 {
00211
00212
00213 std::vector<Eigen::Vector3d> de_meaned (nn_indices.size ());
00214 for (size_t ni = 0; ni < nn_indices.size (); ++ni)
00215 {
00216 de_meaned[ni][0] = input_->points[nn_indices[ni]].x - point[0];
00217 de_meaned[ni][1] = input_->points[nn_indices[ni]].y - point[1];
00218 de_meaned[ni][2] = input_->points[nn_indices[ni]].z - point[2];
00219 nn_sqr_dists[ni] = static_cast<float> (de_meaned[ni].dot (de_meaned[ni]));
00220 }
00221
00222
00223 Eigen::VectorXd weight_vec (nn_indices.size ());
00224 Eigen::MatrixXd P (nr_coeff_, nn_indices.size ());
00225 Eigen::VectorXd f_vec (nn_indices.size ());
00226 Eigen::MatrixXd P_weight;
00227 Eigen::MatrixXd P_weight_Pt (nr_coeff_, nr_coeff_);
00228
00229
00230 v_axis = plane_normal.unitOrthogonal ();
00231 u_axis = plane_normal.cross (v_axis);
00232
00233
00234
00235 double u_coord, v_coord, u_pow, v_pow;
00236 for (size_t ni = 0; ni < nn_indices.size (); ++ni)
00237 {
00238
00239 weight_vec (ni) = exp (-nn_sqr_dists[ni] / sqr_gauss_param_);
00240
00241
00242 u_coord = de_meaned[ni].dot (u_axis);
00243 v_coord = de_meaned[ni].dot (v_axis);
00244 f_vec (ni) = de_meaned[ni].dot (plane_normal);
00245
00246
00247 int j = 0;
00248 u_pow = 1;
00249 for (int ui = 0; ui <= order_; ++ui)
00250 {
00251 v_pow = 1;
00252 for (int vi = 0; vi <= order_ - ui; ++vi)
00253 {
00254 P (j++, ni) = u_pow * v_pow;
00255 v_pow *= v_coord;
00256 }
00257 u_pow *= u_coord;
00258 }
00259 }
00260
00261
00262 P_weight = P * weight_vec.asDiagonal ();
00263 P_weight_Pt = P_weight * P.transpose ();
00264 c_vec = P_weight * f_vec;
00265 P_weight_Pt.llt ().solveInPlace (c_vec);
00266 }
00267
00268 switch (upsample_method_)
00269 {
00270 case (NONE):
00271 {
00272 Eigen::Vector3d normal = plane_normal;
00273
00274 if (polynomial_fit_ && static_cast<int> (nn_indices.size ()) >= nr_coeff_ && pcl_isfinite (c_vec[0]))
00275 {
00276 point += (c_vec[0] * plane_normal);
00277
00278
00279 if (compute_normals_)
00280 normal = plane_normal - c_vec[order_ + 1] * u_axis - c_vec[1] * v_axis;
00281 }
00282
00283 PointOutT aux;
00284 aux.x = static_cast<float> (point[0]);
00285 aux.y = static_cast<float> (point[1]);
00286 aux.z = static_cast<float> (point[2]);
00287 projected_points.push_back (aux);
00288
00289 if (compute_normals_)
00290 {
00291 pcl::Normal aux_normal;
00292 aux_normal.normal_x = static_cast<float> (normal[0]);
00293 aux_normal.normal_y = static_cast<float> (normal[1]);
00294 aux_normal.normal_z = static_cast<float> (normal[2]);
00295 aux_normal.curvature = curvature;
00296 projected_points_normals.push_back (aux_normal);
00297 corresponding_input_indices.indices.push_back (index);
00298 }
00299
00300 break;
00301 }
00302
00303 case (SAMPLE_LOCAL_PLANE):
00304 {
00305
00306 for (float u_disp = -static_cast<float> (upsampling_radius_); u_disp <= upsampling_radius_; u_disp += static_cast<float> (upsampling_step_))
00307 for (float v_disp = -static_cast<float> (upsampling_radius_); v_disp <= upsampling_radius_; v_disp += static_cast<float> (upsampling_step_))
00308 if (u_disp*u_disp + v_disp*v_disp < upsampling_radius_*upsampling_radius_)
00309 {
00310 PointOutT projected_point;
00311 pcl::Normal projected_normal;
00312 projectPointToMLSSurface (u_disp, v_disp, u_axis, v_axis, plane_normal, point,
00313 curvature, c_vec,
00314 static_cast<int> (nn_indices.size ()),
00315 projected_point, projected_normal);
00316
00317 projected_points.push_back (projected_point);
00318 corresponding_input_indices.indices.push_back (index);
00319 if (compute_normals_)
00320 projected_points_normals.push_back (projected_normal);
00321 }
00322 break;
00323 }
00324
00325 case (RANDOM_UNIFORM_DENSITY):
00326 {
00327
00328 int num_points_to_add = static_cast<int> (floor (desired_num_points_in_radius_ / 2.0 / static_cast<double> (nn_indices.size ())));
00329
00330
00331 if (num_points_to_add <= 0)
00332 {
00333
00334 Eigen::Vector3d normal = plane_normal;
00335 if (polynomial_fit_ && static_cast<int> (nn_indices.size ()) >= nr_coeff_ && pcl_isfinite (c_vec[0]))
00336 {
00337
00338 point += (c_vec[0] * plane_normal);
00339
00340 if (compute_normals_)
00341 normal = plane_normal - c_vec[order_ + 1] * u_axis - c_vec[1] * v_axis;
00342 }
00343 PointOutT aux;
00344 aux.x = static_cast<float> (point[0]);
00345 aux.y = static_cast<float> (point[1]);
00346 aux.z = static_cast<float> (point[2]);
00347 projected_points.push_back (aux);
00348 corresponding_input_indices.indices.push_back (index);
00349
00350 if (compute_normals_)
00351 {
00352 pcl::Normal aux_normal;
00353 aux_normal.normal_x = static_cast<float> (normal[0]);
00354 aux_normal.normal_y = static_cast<float> (normal[1]);
00355 aux_normal.normal_z = static_cast<float> (normal[2]);
00356 aux_normal.curvature = curvature;
00357 projected_points_normals.push_back (aux_normal);
00358 }
00359 }
00360 else
00361 {
00362
00363 for (int num_added = 0; num_added < num_points_to_add;)
00364 {
00365 float u_disp = (*rng_uniform_distribution_) (),
00366 v_disp = (*rng_uniform_distribution_) ();
00367
00368 if (u_disp * u_disp + v_disp * v_disp > search_radius_ * search_radius_/4)
00369 continue;
00370
00371
00372 PointOutT projected_point;
00373 pcl::Normal projected_normal;
00374 projectPointToMLSSurface (u_disp, v_disp, u_axis, v_axis, plane_normal, point,
00375 curvature, c_vec,
00376 static_cast<int> (nn_indices.size ()),
00377 projected_point, projected_normal);
00378
00379 projected_points.push_back (projected_point);
00380 corresponding_input_indices.indices.push_back (index);
00381 if (compute_normals_)
00382 projected_points_normals.push_back (projected_normal);
00383
00384 num_added ++;
00385 }
00386 }
00387 break;
00388 }
00389
00390 case (VOXEL_GRID_DILATION):
00391 case (DISTINCT_CLOUD):
00392 {
00393
00394
00395 mls_result = MLSResult (point, plane_normal, u_axis, v_axis, c_vec, static_cast<int> (nn_indices.size ()), curvature);
00396 break;
00397 }
00398 }
00399 }
00400
00402 template <typename PointInT, typename PointOutT> void
00403 pcl::MovingLeastSquares<PointInT, PointOutT>::projectPointToMLSSurface (float &u_disp, float &v_disp,
00404 Eigen::Vector3d &u, Eigen::Vector3d &v,
00405 Eigen::Vector3d &plane_normal,
00406 Eigen::Vector3d &mean,
00407 float &curvature,
00408 Eigen::VectorXd &c_vec,
00409 int num_neighbors,
00410 PointOutT &result_point,
00411 pcl::Normal &result_normal) const
00412 {
00413 double n_disp = 0.0f;
00414 double d_u = 0.0f, d_v = 0.0f;
00415
00416
00417 if (polynomial_fit_ && num_neighbors >= 5*nr_coeff_ && pcl_isfinite (c_vec[0]))
00418 {
00419
00420
00421 int j = 0;
00422 float u_pow = 1.0f, v_pow = 1.0f, u_pow_prev = 1.0f, v_pow_prev = 1.0f;
00423 for (int ui = 0; ui <= order_; ++ui)
00424 {
00425 v_pow = 1;
00426 for (int vi = 0; vi <= order_ - ui; ++vi)
00427 {
00428
00429 n_disp += u_pow * v_pow * c_vec[j++];
00430
00431
00432 if (ui >= 1)
00433 d_u += c_vec[j-1] * ui * u_pow_prev * v_pow;
00434 if (vi >= 1)
00435 d_v += c_vec[j-1] * vi * u_pow * v_pow_prev;
00436
00437 v_pow_prev = v_pow;
00438 v_pow *= v_disp;
00439 }
00440 u_pow_prev = u_pow;
00441 u_pow *= u_disp;
00442 }
00443 }
00444
00445 result_point.x = static_cast<float> (mean[0] + u[0] * u_disp + v[0] * v_disp + plane_normal[0] * n_disp);
00446 result_point.y = static_cast<float> (mean[1] + u[1] * u_disp + v[1] * v_disp + plane_normal[1] * n_disp);
00447 result_point.z = static_cast<float> (mean[2] + u[2] * u_disp + v[2] * v_disp + plane_normal[2] * n_disp);
00448
00449 Eigen::Vector3d normal = plane_normal - d_u * u - d_v * v;
00450 normal.normalize ();
00451
00452 result_normal.normal_x = static_cast<float> (normal[0]);
00453 result_normal.normal_y = static_cast<float> (normal[1]);
00454 result_normal.normal_z = static_cast<float> (normal[2]);
00455 result_normal.curvature = curvature;
00456 }
00457
00459 template <typename PointInT, typename PointOutT> void
00460 pcl::MovingLeastSquares<PointInT, PointOutT>::performProcessing (PointCloudOut &output)
00461 {
00462
00463 nr_coeff_ = (order_ + 1) * (order_ + 2) / 2;
00464
00465
00466
00467 std::vector<int> nn_indices;
00468 std::vector<float> nn_sqr_dists;
00469
00470
00471 for (size_t cp = 0; cp < indices_->size (); ++cp)
00472 {
00473
00474 if (!searchForNeighbors ((*indices_)[cp], nn_indices, nn_sqr_dists))
00475 continue;
00476
00477
00478
00479
00480 if (nn_indices.size () < 3)
00481 continue;
00482
00483
00484 PointCloudOut projected_points;
00485 NormalCloud projected_points_normals;
00486
00487 int index = (*indices_)[cp];
00488 computeMLSPointNormal (index, nn_indices, nn_sqr_dists, projected_points, projected_points_normals, *corresponding_input_indices_, mls_results_[index]);
00489
00490
00491
00492 for (size_t pp = 0; pp < projected_points.size (); ++pp)
00493 copyMissingFields (input_->points[(*indices_)[cp]], projected_points[pp]);
00494
00495
00496
00497 output.insert (output.end (), projected_points.begin (), projected_points.end ());
00498 if (compute_normals_)
00499 normals_->insert (normals_->end (), projected_points_normals.begin (), projected_points_normals.end ());
00500 }
00501
00502
00503 performUpsampling (output);
00504 }
00505
00507 #ifdef _OPENMP
00508 template <typename PointInT, typename PointOutT> void
00509 pcl::MovingLeastSquaresOMP<PointInT, PointOutT>::performProcessing (PointCloudOut &output)
00510 {
00511
00512 nr_coeff_ = (order_ + 1) * (order_ + 2) / 2;
00513
00514
00515 unsigned int threads = threads_ == 0 ? 1 : threads_;
00516
00517
00518 typename PointCloudOut::CloudVectorType projected_points (threads);
00519 typename NormalCloud::CloudVectorType projected_points_normals (threads);
00520 std::vector<PointIndices> corresponding_input_indices (threads);
00521
00522
00523 #pragma omp parallel for schedule (dynamic,1000) num_threads (threads)
00524 for (int cp = 0; cp < static_cast<int> (indices_->size ()); ++cp)
00525 {
00526
00527
00528 std::vector<int> nn_indices;
00529 std::vector<float> nn_sqr_dists;
00530
00531
00532 if (this->searchForNeighbors ((*indices_)[cp], nn_indices, nn_sqr_dists))
00533 {
00534
00535
00536 if (nn_indices.size () >= 3)
00537 {
00538
00539 int tn = omp_get_thread_num ();
00540
00541
00542 size_t pp_size = projected_points[tn].size ();
00543
00544
00545 int index = (*indices_)[cp];
00546 this->computeMLSPointNormal (index, nn_indices, nn_sqr_dists, projected_points[tn], projected_points_normals[tn], corresponding_input_indices[tn], this->mls_results_[index]);
00547
00548
00549 for (size_t pp = pp_size; pp < projected_points[tn].size (); ++pp)
00550 this->copyMissingFields (input_->points[(*indices_)[cp]], projected_points[tn][pp]);
00551 }
00552 }
00553 }
00554
00555
00556
00557 for (unsigned int tn = 0; tn < threads; ++tn)
00558 {
00559 output.insert (output.end (), projected_points[tn].begin (), projected_points[tn].end ());
00560 corresponding_input_indices_->indices.insert (corresponding_input_indices_->indices.end (),
00561 corresponding_input_indices[tn].indices.begin (), corresponding_input_indices[tn].indices.end ());
00562 if (compute_normals_)
00563 normals_->insert (normals_->end (), projected_points_normals[tn].begin (), projected_points_normals[tn].end ());
00564 }
00565
00566
00567 this->performUpsampling (output);
00568 }
00569 #endif
00570
00572 template <typename PointInT, typename PointOutT> void
00573 pcl::MovingLeastSquares<PointInT, PointOutT>::performUpsampling (PointCloudOut &output)
00574 {
00575 if (upsample_method_ == DISTINCT_CLOUD)
00576 {
00577 for (size_t dp_i = 0; dp_i < distinct_cloud_->size (); ++dp_i)
00578 {
00579
00580 if (!pcl_isfinite (distinct_cloud_->points[dp_i].x))
00581 continue;
00582
00583
00584
00585 std::vector<int> nn_indices;
00586 std::vector<float> nn_dists;
00587 tree_->nearestKSearch (distinct_cloud_->points[dp_i], 1, nn_indices, nn_dists);
00588 int input_index = nn_indices.front ();
00589
00590
00591
00592 if (mls_results_[input_index].valid == false)
00593 continue;
00594
00595 Eigen::Vector3d add_point = distinct_cloud_->points[dp_i].getVector3fMap ().template cast<double> ();
00596
00597 float u_disp = static_cast<float> ((add_point - mls_results_[input_index].mean).dot (mls_results_[input_index].u_axis)),
00598 v_disp = static_cast<float> ((add_point - mls_results_[input_index].mean).dot (mls_results_[input_index].v_axis));
00599
00600 PointOutT result_point;
00601 pcl::Normal result_normal;
00602 projectPointToMLSSurface (u_disp, v_disp,
00603 mls_results_[input_index].u_axis, mls_results_[input_index].v_axis,
00604 mls_results_[input_index].plane_normal,
00605 mls_results_[input_index].mean,
00606 mls_results_[input_index].curvature,
00607 mls_results_[input_index].c_vec,
00608 mls_results_[input_index].num_neighbors,
00609 result_point, result_normal);
00610
00611
00612 copyMissingFields (input_->points[input_index], result_point);
00613
00614
00615 corresponding_input_indices_->indices.push_back (input_index);
00616
00617 output.push_back (result_point);
00618 if (compute_normals_)
00619 normals_->push_back (result_normal);
00620 }
00621 }
00622
00623
00624
00625 if (upsample_method_ == VOXEL_GRID_DILATION)
00626 {
00627 MLSVoxelGrid voxel_grid (input_, indices_, voxel_size_);
00628 for (int iteration = 0; iteration < dilation_iteration_num_; ++iteration)
00629 voxel_grid.dilate ();
00630
00631 for (typename MLSVoxelGrid::HashMap::iterator m_it = voxel_grid.voxel_grid_.begin (); m_it != voxel_grid.voxel_grid_.end (); ++m_it)
00632 {
00633
00634 Eigen::Vector3f pos;
00635 voxel_grid.getPosition (m_it->first, pos);
00636
00637 PointInT p;
00638 p.x = pos[0];
00639 p.y = pos[1];
00640 p.z = pos[2];
00641
00642 std::vector<int> nn_indices;
00643 std::vector<float> nn_dists;
00644 tree_->nearestKSearch (p, 1, nn_indices, nn_dists);
00645 int input_index = nn_indices.front ();
00646
00647
00648
00649 if (mls_results_[input_index].valid == false)
00650 continue;
00651
00652 Eigen::Vector3d add_point = p.getVector3fMap ().template cast<double> ();
00653 float u_disp = static_cast<float> ((add_point - mls_results_[input_index].mean).dot (mls_results_[input_index].u_axis)),
00654 v_disp = static_cast<float> ((add_point - mls_results_[input_index].mean).dot (mls_results_[input_index].v_axis));
00655
00656 PointOutT result_point;
00657 pcl::Normal result_normal;
00658 projectPointToMLSSurface (u_disp, v_disp,
00659 mls_results_[input_index].u_axis, mls_results_[input_index].v_axis,
00660 mls_results_[input_index].plane_normal,
00661 mls_results_[input_index].mean,
00662 mls_results_[input_index].curvature,
00663 mls_results_[input_index].c_vec,
00664 mls_results_[input_index].num_neighbors,
00665 result_point, result_normal);
00666
00667
00668 copyMissingFields (input_->points[input_index], result_point);
00669
00670
00671 corresponding_input_indices_->indices.push_back (input_index);
00672
00673 output.push_back (result_point);
00674
00675 if (compute_normals_)
00676 normals_->push_back (result_normal);
00677 }
00678 }
00679 }
00680
00682 template <typename PointInT, typename PointOutT>
00683 pcl::MovingLeastSquares<PointInT, PointOutT>::MLSResult::MLSResult (const Eigen::Vector3d &a_mean,
00684 const Eigen::Vector3d &a_plane_normal,
00685 const Eigen::Vector3d &a_u,
00686 const Eigen::Vector3d &a_v,
00687 const Eigen::VectorXd a_c_vec,
00688 const int a_num_neighbors,
00689 const float &a_curvature) :
00690 mean (a_mean), plane_normal (a_plane_normal), u_axis (a_u), v_axis (a_v), c_vec (a_c_vec), num_neighbors (a_num_neighbors),
00691 curvature (a_curvature), valid (true)
00692 {
00693 }
00694
00696 template <typename PointInT, typename PointOutT>
00697 pcl::MovingLeastSquares<PointInT, PointOutT>::MLSVoxelGrid::MLSVoxelGrid (PointCloudInConstPtr& cloud,
00698 IndicesPtr &indices,
00699 float voxel_size) :
00700 voxel_grid_ (), bounding_min_ (), bounding_max_ (), data_size_ (), voxel_size_ (voxel_size)
00701 {
00702 pcl::getMinMax3D (*cloud, *indices, bounding_min_, bounding_max_);
00703
00704 Eigen::Vector4f bounding_box_size = bounding_max_ - bounding_min_;
00705 double max_size = (std::max) ((std::max)(bounding_box_size.x (), bounding_box_size.y ()), bounding_box_size.z ());
00706
00707 data_size_ = static_cast<uint64_t> (1.5 * max_size / voxel_size_);
00708 for (unsigned int i = 0; i < indices->size (); ++i)
00709 if (pcl_isfinite (cloud->points[(*indices)[i]].x))
00710 {
00711 Eigen::Vector3i pos;
00712 getCellIndex (cloud->points[(*indices)[i]].getVector3fMap (), pos);
00713
00714 uint64_t index_1d;
00715 getIndexIn1D (pos, index_1d);
00716 Leaf leaf;
00717 voxel_grid_[index_1d] = leaf;
00718 }
00719 }
00720
00722 template <typename PointInT, typename PointOutT> void
00723 pcl::MovingLeastSquares<PointInT, PointOutT>::MLSVoxelGrid::dilate ()
00724 {
00725 HashMap new_voxel_grid = voxel_grid_;
00726 for (typename MLSVoxelGrid::HashMap::iterator m_it = voxel_grid_.begin (); m_it != voxel_grid_.end (); ++m_it)
00727 {
00728 Eigen::Vector3i index;
00729 getIndexIn3D (m_it->first, index);
00730
00731
00732 for (int x = -1; x <= 1; ++x)
00733 for (int y = -1; y <= 1; ++y)
00734 for (int z = -1; z <= 1; ++z)
00735 if (x != 0 || y != 0 || z != 0)
00736 {
00737 Eigen::Vector3i new_index;
00738 new_index = index + Eigen::Vector3i (x, y, z);
00739
00740 uint64_t index_1d;
00741 getIndexIn1D (new_index, index_1d);
00742 Leaf leaf;
00743 new_voxel_grid[index_1d] = leaf;
00744 }
00745 }
00746 voxel_grid_ = new_voxel_grid;
00747 }
00748
00749
00751 template <typename PointInT, typename PointOutT> void
00752 pcl::MovingLeastSquares<PointInT, PointOutT>::copyMissingFields (const PointInT &point_in,
00753 PointOutT &point_out) const
00754 {
00755 typedef typename pcl::traits::fieldList<typename PointCloudIn::PointType>::type FieldListInput;
00756 typedef typename pcl::traits::fieldList<typename PointCloudOut::PointType>::type FieldListOutput;
00757 typedef typename pcl::intersect<FieldListInput, FieldListOutput>::type FieldList;
00758
00759 PointOutT temp = point_out;
00760 pcl::for_each_type <FieldList> (pcl::NdConcatenateFunctor <PointInT, PointOutT> (point_in,
00761 point_out));
00762 point_out.x = temp.x;
00763 point_out.y = temp.y;
00764 point_out.z = temp.z;
00765 }
00766
00767
00768 #define PCL_INSTANTIATE_MovingLeastSquares(T,OutT) template class PCL_EXPORTS pcl::MovingLeastSquares<T,OutT>;
00769
00770 #ifdef _OPENMP
00771 #define PCL_INSTANTIATE_MovingLeastSquaresOMP(T,OutT) template class PCL_EXPORTS pcl::MovingLeastSquaresOMP<T,OutT>;
00772 #endif
00773
00774 #endif // PCL_SURFACE_IMPL_MLS_H_