PCL - MLS代碼研讀(十一)- computeMLSPointNormal函數
-
- 前言
- computeMLSPointNormal
前言
在PCL - MLS代碼研讀(十)- performProcessing函數中,看到了
performProcessing
函數調用
computeMLSPointNormal
函數做計算,得到投影點坐標及法向量。實際上在此函數中,還會根據
upsample_method_
所指定的上採樣方法做上採樣。
computeMLSPointNormal
根據
upsample_method_
決定要如何投影及上採樣。如果上採樣方式是
SAMPLE_LOCAL_PLANE
或
RANDOM_UNIFORM_DENSITY
,則在此完成上採樣。否則調用
performUpsampling
函數做上採樣。
template <typename PointInT, typename PointOutT> void
pcl::MovingLeastSquares<PointInT, PointOutT>::computeMLSPointNormal (pcl::index_t index,
const pcl::Indices &nn_indices,
PointCloudOut &projected_points,
NormalCloud &projected_points_normals,
PointIndices &corresponding_input_indices,
MLSResult &mls_result) const
{
// Note: this method is const because it needs to be thread-safe
// (MovingLeastSquaresOMP calls it from multiple threads)
調用
computeMLSSurface
函數:
如果上採樣方法是
NONE
,調用
projectQueryPoint
得到
proj
這個投影結果,然後調用
addProjectedPointNormal
將結果新增到
projected_points
,
projected_points_normals
,
corresponding_input_indices
。
switch (upsample_method_)
{
case (NONE):
{
const MLSResult::MLSProjectionResults proj = mls_result.projectQueryPoint (projection_method_, nr_coeff_);
addProjectedPointNormal (index, proj.point, proj.normal, mls_result.curvature, projected_points, projected_points_normals, corresponding_input_indices);
break;
}
在半徑
upsampling_radius_
的範圍內,在u和v方向上每隔
upsampling_step_
的距離取一個點,然後投影到平面上:
case (SAMPLE_LOCAL_PLANE):
{
// Uniformly sample a circle around the query point using the radius and step parameters
for (float u_disp = -static_cast<float> (upsampling_radius_); u_disp <= upsampling_radius_; u_disp += static_cast<float> (upsampling_step_))
for (float v_disp = -static_cast<float> (upsampling_radius_); v_disp <= upsampling_radius_; v_disp += static_cast<float> (upsampling_step_))
if (u_disp * u_disp + v_disp * v_disp < upsampling_radius_ * upsampling_radius_)
{
MLSResult::MLSProjectionResults proj = mls_result.projectPointSimpleToPolynomialSurface (u_disp, v_disp);
addProjectedPointNormal (index, proj.point, proj.normal, mls_result.curvature, projected_points, projected_points_normals, corresponding_input_indices);
}
break;
}
RANDOM_UNIFORM_DENSITY
上採樣方法暫時不做介紹:
case (RANDOM_UNIFORM_DENSITY):
{
// Compute the local point density and add more samples if necessary
const int num_points_to_add = static_cast<int> (std::floor (desired_num_points_in_radius_ / 2.0 / static_cast<double> (nn_indices.size ())));
// Just add the query point, because the density is good
if (num_points_to_add <= 0)
{
// Just add the current point
const MLSResult::MLSProjectionResults proj = mls_result.projectQueryPoint (projection_method_, nr_coeff_);
addProjectedPointNormal (index, proj.point, proj.normal, mls_result.curvature, projected_points, projected_points_normals, corresponding_input_indices);
}
else
{
// Sample the local plane
for (int num_added = 0; num_added < num_points_to_add;)
{
const double u = (*rng_uniform_distribution_) (rng_);
const double v = (*rng_uniform_distribution_) (rng_);
// Check if inside circle; if not, try another coin flip
if (u * u + v * v > search_radius_ * search_radius_ / 4)
continue;
MLSResult::MLSProjectionResults proj;
if (order_ > 1 && mls_result.num_neighbors >= 5 * nr_coeff_)
proj = mls_result.projectPointSimpleToPolynomialSurface (u, v);
else
proj = mls_result.projectPointToMLSPlane (u, v);
addProjectedPointNormal (index, proj.point, proj.normal, mls_result.curvature, projected_points, projected_points_normals, corresponding_input_indices);
num_added++;
}
}
break;
}
default:
break;
}
}