目录
一、算法原理
针对正三棱锥(四面体)表面均匀点云的生成,采用基于重心坐标的随机采样方法。对于任意三角形,其顶点为 A , B , C A,B,C A,B,C,随机点 P P P由如下凸组合定义:
P = ( 1 − ξ 1 − ξ 2 ) A + ξ 1 B + ξ 2 C P=(1 - \xi_1 - \xi_2)\,\mathbf{A} + \xi_1\,\mathbf{B} + \xi_2\,\mathbf{C} P=(1−ξ1−ξ2)A+ξ1B+ξ2C
其中 ξ 1 , ξ 2 \xi_1, \xi_2 ξ1,ξ2 服从标准二维单纯形 { ξ 1 ≥ 0 , ξ 2 ≥ 0 , ξ 1 + ξ 2 ≤ 1 } \{\xi_1 \ge 0,\; \xi_2 \ge 0,\; \xi_1+\xi_2 \le 1\} {ξ1≥0,ξ2≥0,ξ1+ξ2≤1} 上的均匀分布。实际计算时,首先生成两个独立的均匀随机变量 U , V ∼ U 0 , 1 U, V \sim \mathcal{U}0,1 U,V∼U0,1,仅当 U + V ≤ 1 U+V \le 1 U+V≤1 时接受该数对;否则拒绝并重新采样。这一拒绝机制确保了点集在三角形区域内呈均匀分布。
将该过程分别应用于三棱锥的四个三角面------底面与三个侧面------即可得到该多面体表面的稠密点云。各面独立采样,互不影响,整体点云在表面积上具有无偏均匀性。
二、代码实现
cpp
#include <vector>
#include <random>
#include <iostream>
#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
#include <pcl/io/pcd_io.h>
#include <pcl/visualization/pcl_visualizer.h>
// 生成三棱锥点云
pcl::PointCloud<pcl::PointXYZ>::Ptr generatePyramidCloud()
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
// 定义三棱锥的四个顶点
std::vector<pcl::PointXYZ> vertices =
{
pcl::PointXYZ(0.0f, 0.0f, 0.0f), // 底面三角形顶点1
pcl::PointXYZ(1.0f, 0.0f, 0.0f), // 底面三角形顶点2
pcl::PointXYZ(0.5f, 0.866f, 0.0f), // 底面三角形顶点3
pcl::PointXYZ(0.5f, 0.288f, 1.0f) // 顶点
};
// 在三个面上生成随机点
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<> dis(0.0, 1.0);
// 生成底面三角形内部点
for (int i = 0; i < 20000; ++i)
{
float r1 = dis(gen);
float r2 = dis(gen);
if (r1 + r2 <= 1.0f)
{
pcl::PointXYZ p;
p.x = (1 - r1 - r2) * vertices[0].x + r1 * vertices[1].x + r2 * vertices[2].x;
p.y = (1 - r1 - r2) * vertices[0].y + r1 * vertices[1].y + r2 * vertices[2].y;
p.z = 0.0f;
cloud->points.push_back(p);
}
else
{
i--; // 重新生成
}
}
// 生成三个侧面的点
for (int face = 0; face < 3; ++face)
{
int v1 = face;
int v2 = (face + 1) % 3;
int v3 = 3; // 顶点
for (int i = 0; i < 20000; ++i)
{
float r1 = dis(gen);
float r2 = dis(gen);
if (r1 + r2 <= 1.0f)
{
pcl::PointXYZ p;
p.x = (1 - r1 - r2) * vertices[v1].x + r1 * vertices[v2].x + r2 * vertices[v3].x;
p.y = (1 - r1 - r2) * vertices[v1].y + r1 * vertices[v2].y + r2 * vertices[v3].y;
p.z = (1 - r1 - r2) * vertices[v1].z + r1 * vertices[v2].z + r2 * vertices[v3].z;
cloud->points.push_back(p);
}
else
{
i--;
}
}
}
cloud->width = cloud->points.size();
cloud->height = 1;
cloud->is_dense = true;
return cloud;
}
int main()
{
// 生成模拟三棱锥点云
std::cout << "生成三棱锥点云..." << std::endl;
pcl::PointCloud<pcl::PointXYZ>::Ptr pyramid_cloud = generatePyramidCloud();
std::cout << "点云数量: " << pyramid_cloud->size() << " 个点" << std::endl;
// 保存模拟点云
pcl::io::savePCDFileBinary("pyramid_cloud.pcd", *pyramid_cloud);
std::cout << "已保存模拟点云到: pyramid_cloud.pcd" << std::endl;
// 可视化
pcl::visualization::PCLVisualizer viewer("Pyramid");
viewer.setBackgroundColor(0.1, 0.1, 0.1);
// 添加原始点云
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> cloud_color(pyramid_cloud, 100, 100, 100);
viewer.addPointCloud(pyramid_cloud, cloud_color, "pyramid_cloud");
viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "pyramid_cloud");
std::cout << "\n按q退出可视化窗口..." << std::endl;
viewer.spin();
return 0;
}
三、结果展示
