PCL 生成三棱锥点云

目录

一、算法原理

  针对正三棱锥(四面体)表面均匀点云的生成,采用基于重心坐标的随机采样方法。对于任意三角形,其顶点为 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;
}

三、结果展示

相关推荐
玖玥拾22 分钟前
C/C++ 数据结构(七)栈、容器适配器
c语言·数据结构·c++··容器适配器
何以解忧,唯有..30 分钟前
Go语言循环语句详解:for、range与循环控制
开发语言·算法·golang
想吃火锅10051 小时前
【leetcode】88.合并两个有序数组js
算法
один but you2 小时前
constexpr函数
c++
生成论实验室2 小时前
机器人:一个自主运动的系统
人工智能·算法·语言模型·机器人·自动驾驶·agi·安全架构
Qres8212 小时前
算法复键——树状数组
数据结构·算法
H178535090962 小时前
SolidWorks第四部分_直接实体建模特征9_替换面原理
线性代数·算法·机器学习·3d建模·solidworks
凡人叶枫2 小时前
Effective C++ 条款41:了解隐式接口和编译期多态
java·开发语言·c++·effective c++
不会就选b2 小时前
算法日常・每日刷题--<二分查找>3
算法
凡人叶枫2 小时前
Effective C++ 条款42:了解 typename 的双重意义
java·linux·服务器·c++