一、算法概述
使用Voronoi协方差度量检测点云的尖锐边缘特征点。
1、主要函数
头文件
#include <CGAL/vcm_estimate_edges.h>
函数
bool CGAL::vcm_is_on_feature_edge ( std::array< FT, 6 > & cov,
double threshold,
VCMTraits
)
确定一个点是否从计算Voronoi协方差度量的点集上的尖锐特征边缘。利用边缘的锐度阈值参数,根据锐度特征周围的外部角度进行点滤波。
假设一个点在边缘的外角为:
α
\alpha
α,如果
α
\alpha
α满足如下公式:
α
≥
2
3
\alpha\geq\frac{2}{\sqrt{3}}
α≥32
则认为该点在一个尖锐特征上。
这意味着如果输入点云包含外部角度不同的尖锐特征,应该考虑外部角度最小的特征,但这会导致在更尖锐的区域选择更多的点。
2、参考文献
[1] Quentin Merigot, Maks Ovsjanikov, and Leonidas Guibas. Voronoi-based curvature and feature estimation from point clouds. Visualization and Computer Graphics, IEEE Transactions on, 17(6):743–756, 2011.
二、代码实现
#include <utility> // std::pair
#include <vector>
#include <fstream>
#include <CGAL/property_map.h>
#include <CGAL/IO/read_points.h>
#include <CGAL/IO/write_points.h>
#include <CGAL/vcm_estimate_edges.h> // 计算vo协方差
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
// Types
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
// 存储点坐标和法向量的pair容器
typedef std::pair<Kernel::Point_3, Kernel::Vector_3> PointVectorPair;
// 数组
typedef std::array<double, 6> Covariance;
int main(int, char**)
{
const std::string input_filename = CGAL::data_file_path("cgal//fandisk_large.off");
const char* output_filename("cgal//fandisk_large.xyz");
// -----------------------从模型数据中读取点坐标和法线-----------------------
std::list<PointVectorPair> points;
if (!CGAL::IO::read_points(input_filename, std::back_inserter(points),
CGAL::parameters::point_map(CGAL::First_of_pair_property_map<PointVectorPair>())))
{
std::cerr << "Error: cannot read file data/fandisk_large.off" << std::endl;
return -1;
}
// -----------------------------计算每个点的协方差---------------------------
double R = 0.2,
r = 0.1;
std::vector<Covariance> cov;
CGAL::First_of_pair_property_map<PointVectorPair> point_map;
CGAL::compute_vcm(points, cov, R, r,
CGAL::parameters::point_map(point_map).geom_traits(Kernel()));
// ------------------------------找到边缘上的点------------------------------
// 这个步骤可以多执行几次,以获取更好的结果
double threshold = 0.16;
std::ofstream output("cgal//points_on_edges.xyz");
int i = 0;
for (auto& p : points)
{
if (CGAL::vcm_is_on_feature_edge(cov[i], threshold))
output << p.first << "\n";
++i;
}
output.close();
return 0;
}