PCL 1.15.1的common/distances.h详细分析

一、distances.h 整体概述

这个头文件定义了PCL中常用的距离计算函数,主要包括:

  1. 线段相关距离计算 (lineToLineSegment, sqrPointToLineDistance)
  2. 最大距离段查找 (getMaxSegment)
  3. 欧氏距离计算 (euclideanDistance, squaredEuclideanDistance)

这些函数是PCL许多高级算法的基础,如分割、配准、特征提取等。


二、线到线的最短线段计算

2.1 函数原型

PCL_EXPORTS void
lineToLineSegment (const Eigen::VectorXf &line_a, 
                   const Eigen::VectorXf &line_b, 
                   Eigen::Vector4f &pt1_seg, 
                   Eigen::Vector4f &pt2_seg);

2.2 功能说明

计算两条三维直线之间的最短线段,返回该线段的两个端点。

参数解析:

  • line_a: 第一条直线的系数(点+方向),格式为[px, py, pz, dx, dy, dz]
  • line_b: 第二条直线的系数(点+方向),格式相同
  • pt1_seg: 输出的线段第一个端点(在line_a上)
  • pt2_seg: 输出的线段第二个端点(在line_b上)

2.3 数学原理

两条空间直线的最短距离问题:

  • 直线A: P = P₀ + t·d₀
  • 直线B: Q = Q₀ + s·d₁
  • 最短距离的线段垂直于两条直线

2.4 完整使用示例

#include <pcl/common/distances.h>
#include <Eigen/Core>
#include <iostream>

int main()
{
    // 定义第一条直线: 过点(0,0,0), 方向为(1,0,0)
    Eigen::VectorXf line_a(6);
    line_a << 0.0f, 0.0f, 0.0f,  // 直线上的点
              1.0f, 0.0f, 0.0f;  // 方向向量

    // 定义第二条直线: 过点(0,1,1), 方向为(0,1,0)
    Eigen::VectorXf line_b(6);
    line_b << 0.0f, 1.0f, 1.0f,  // 直线上的点
              0.0f, 1.0f, 0.0f;  // 方向向量

    // 存储结果的端点
    Eigen::Vector4f pt1_seg, pt2_seg;

    // 计算最短线段
    pcl::lineToLineSegment(line_a, line_b, pt1_seg, pt2_seg);

    std::cout << "最短线段端点1 (在line_a上): " 
              << pt1_seg.transpose() << std::endl;
    std::cout << "最短线段端点2 (在line_b上): " 
              << pt2_seg.transpose() << std::endl;
    
    // 计算最短距离
    float min_distance = (pt1_seg - pt2_seg).norm();
    std::cout << "两直线间的最短距离: " << min_distance << std::endl;

    return 0;
}

2.5 在PCL中的应用场景

  • 直线拟合后的距离评估: 在RANSAC直线拟合中评估两个候选直线模型
  • 线特征匹配: 比较两个点云中提取的线特征
  • 机器人路径规划: 计算两条轨迹之间的最小间隙

三、点到线的距离计算

3.1 第一个重载版本

double inline
sqrPointToLineDistance (const Eigen::Vector4f &pt, 
                        const Eigen::Vector4f &line_pt, 
                        const Eigen::Vector4f &line_dir)

功能: 计算点到直线的平方距离(自动计算方向向量的模)

数学公式:

D² = ||line_dir × (line_pt - pt)||² / ||line_dir||²

参数说明:

  • pt: 待测点(确保pt[3] = 0或1)
  • line_pt: 直线上的一点(重要: line_pt[3]必须为0)
  • line_dir: 直线的方向向量

3.2 第二个重载版本(优化版)

double inline
sqrPointToLineDistance (const Eigen::Vector4f &pt, 
                        const Eigen::Vector4f &line_pt, 
                        const Eigen::Vector4f &line_dir, 
                        const double sqr_length)

功能: 计算点到直线的平方距离(使用预计算的方向向量平方模)

优势: 当需要计算多个点到同一直线的距离时,可预先计算sqr_length = line_dir.squaredNorm(),避免重复计算

参数说明:

  • 前三个参数同上
  • sqr_length: 直线方向向量的平方模(预计算值)

3.3 两个重载的对比使用

#include <pcl/common/distances.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <iostream>
#include <chrono>

int main()
{
    // 定义一条直线: 过原点,沿X轴方向
    Eigen::Vector4f line_pt(0.0f, 0.0f, 0.0f, 0.0f);  // 注意第4个分量为0
    Eigen::Vector4f line_dir(1.0f, 0.0f, 0.0f, 0.0f);
    
    // 定义测试点
    Eigen::Vector4f test_pt(2.0f, 3.0f, 4.0f, 0.0f);
    
    // === 方法1: 基本版本 ===
    double dist_sqr_1 = pcl::sqrPointToLineDistance(test_pt, line_pt, line_dir);
    std::cout << "点到直线的平方距离 (方法1): " << dist_sqr_1 << std::endl;
    std::cout << "点到直线的距离: " << std::sqrt(dist_sqr_1) << std::endl;
    
    // === 方法2: 优化版本(多点计算时使用) ===
    // 模拟1000个点到同一直线的距离计算
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
    cloud->width = 1000;
    cloud->height = 1;
    cloud->points.resize(1000);
    
    // 填充随机点
    for (auto& pt : cloud->points) {
        pt.x = rand() % 100;
        pt.y = rand() % 100;
        pt.z = rand() % 100;
    }
    
    // 预计算方向向量的平方模
    double sqr_length = line_dir.squaredNorm();
    
    // 性能对比
    auto start1 = std::chrono::high_resolution_clock::now();
    for (const auto& pt : cloud->points) {
        Eigen::Vector4f point = pt.getVector4fMap();
        double d = pcl::sqrPointToLineDistance(point, line_pt, line_dir);
    }
    auto end1 = std::chrono::high_resolution_clock::now();
    
    auto start2 = std::chrono::high_resolution_clock::now();
    for (const auto& pt : cloud->points) {
        Eigen::Vector4f point = pt.getVector4fMap();
        double d = pcl::sqrPointToLineDistance(point, line_pt, line_dir, sqr_length);
    }
    auto end2 = std::chrono::high_resolution_clock::now();
    
    std::cout << "\n性能对比 (1000个点):" << std::endl;
    std::cout << "方法1耗时: " 
              << std::chrono::duration_cast<std::chrono::microseconds>(end1-start1).count() 
              << " μs" << std::endl;
    std::cout << "方法2耗时: " 
              << std::chrono::duration_cast<std::chrono::microseconds>(end2-start2).count() 
              << " μs" << std::endl;
    
    return 0;
}

3.4 注意事项与常见错误

⚠️ 重要提醒:

// ❌ 错误用法: line_pt的第4个分量不为0
Eigen::Vector4f line_pt(1.0f, 2.0f, 3.0f, 1.0f);  // 错误!

// ✅ 正确用法
Eigen::Vector4f line_pt(1.0f, 2.0f, 3.0f, 0.0f);  // 正确

代码注释明确说明:make sure that line_pt[3] = 0 as there are no internal checks!

3.5 在PCL中的应用

这两个函数广泛用于:

  1. RANSAC平面/直线拟合
// 在pcl::SACSegmentation中评估点到模型的距离
// 伪代码示例
for (each point in inlier_candidates) {
    double dist = sqrPointToLineDistance(point, model_line_pt, model_line_dir);
    if (dist < threshold_squared)
        inliers.push_back(point);
}
  1. 边缘检测
// 判断点是否在边缘线附近
if (sqrPointToLineDistance(query_pt, edge_line_pt, edge_dir) < tolerance)
    is_near_edge = true;
  1. 点云投影到直线
// 计算最近点位置
Eigen::Vector4f projection = line_pt + 
    ((pt - line_pt).dot(line_dir) / line_dir.squaredNorm()) * line_dir;

四、最大线段查找函数 (getMaxSegment)

这是一组模板函数,用于在点云中找到距离最远的两个点(即点云的"直径")。

4.1 第一个重载版本(处理完整点云)

template <typename PointT> double inline
getMaxSegment (const pcl::PointCloud<PointT> &cloud, 
               PointT &pmin, PointT &pmax)

功能: 在整个点云中找到距离最远的两个点

参数说明:

  • cloud: 输入点云
  • pmin: 输出最大线段的一个端点
  • pmax: 输出最大线段的另一个端点
  • 返回值: 最大线段的长度(欧氏距离)

4.2 第二个重载版本(处理索引子集)

template <typename PointT> double inline
getMaxSegment (const pcl::PointCloud<PointT> &cloud, 
               const Indices &indices,
               PointT &pmin, PointT &pmax)

功能: 在点云的指定索引子集中找到距离最远的两个点

参数说明:

  • cloud: 输入点云
  • indices: 要处理的点的索引列表
  • pmin, pmax: 输出端点
  • 返回值: 最大线段的长度

4.3 算法原理分析

// 伪代码展示算法逻辑
max_dist = 最小值
for i in 点集:
    for j in 点集(从i开始):
        dist = distance(点i, 点j)的平方
        if dist > max_dist:
            max_dist = dist
            记录i和j的索引
            
return sqrt(max_dist)  // 返回实际距离而非平方距离

时间复杂度: O(n²),其中n是点的数量 空间复杂度: O(1)

4.4 完整使用示例

#include <pcl/common/distances.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <iostream>

// 示例1: 处理完整点云
void example_full_cloud()
{
    std::cout << "=== 示例1: 完整点云的最大线段 ===" << std::endl;
    
    // 创建点云
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
    
    // 添加一些测试点
    cloud->points.push_back(pcl::PointXYZ(0.0f, 0.0f, 0.0f));
    cloud->points.push_back(pcl::PointXYZ(1.0f, 0.0f, 0.0f));
    cloud->points.push_back(pcl::PointXYZ(0.0f, 1.0f, 0.0f));
    cloud->points.push_back(pcl::PointXYZ(5.0f, 5.0f, 5.0f));  // 最远点
    cloud->points.push_back(pcl::PointXYZ(-3.0f, -3.0f, -3.0f)); // 另一个最远点
    cloud->points.push_back(pcl::PointXYZ(0.5f, 0.5f, 0.5f));
    
    cloud->width = cloud->points.size();
    cloud->height = 1;
    cloud->is_dense = true;
    
    // 查找最大线段
    pcl::PointXYZ pmin, pmax;
    double max_length = pcl::getMaxSegment(*cloud, pmin, pmax);
    
    std::cout << "最大线段长度: " << max_length << std::endl;
    std::cout << "端点1: (" << pmin.x << ", " << pmin.y << ", " << pmin.z << ")" << std::endl;
    std::cout << "端点2: (" << pmax.x << ", " << pmax.y << ", " << pmax.z << ")" << std::endl;
    
    // 验证计算
    float dx = pmax.x - pmin.x;
    float dy = pmax.y - pmin.y;
    float dz = pmax.z - pmin.z;
    double verify_dist = std::sqrt(dx*dx + dy*dy + dz*dz);
    std::cout << "验证距离: " << verify_dist << std::endl;
}

// 示例2: 使用索引处理点云子集
void example_with_indices()
{
    std::cout << "\n=== 示例2: 使用索引的最大线段 ===" << std::endl;
    
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
    
    // 创建一个较大的点云
    for (int i = 0; i < 20; ++i) {
        cloud->points.push_back(pcl::PointXYZ(i * 0.1f, i * 0.1f, 0.0f));
    }
    cloud->width = cloud->points.size();
    cloud->height = 1;
    
    // 只处理部分点(索引5到15)
    pcl::Indices indices;
    for (int i = 5; i < 15; ++i) {
        indices.push_back(i);
    }
    
    pcl::PointXYZ pmin, pmax;
    double max_length = pcl::getMaxSegment(*cloud, indices, pmin, pmax);
    
    std::cout << "子集中的最大线段长度: " << max_length << std::endl;
    std::cout << "端点1: (" << pmin.x << ", " << pmin.y << ", " << pmin.z << ")" << std::endl;
    std::cout << "端点2: (" << pmax.x << ", " << pmax.y << ", " << pmax.z << ")" << std::endl;
}

// 示例3: 实际应用 - 计算点云包围盒的对角线
void example_bounding_box_diagonal()
{
    std::cout << "\n=== 示例3: 包围盒对角线估计 ===" << std::endl;
    
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
    
    // 模拟一个立方体点云
    for (float x = 0; x <= 10; x += 1.0f) {
        for (float y = 0; y <= 10; y += 1.0f) {
            for (float z = 0; z <= 10; z += 1.0f) {
                cloud->points.push_back(pcl::PointXYZ(x, y, z));
            }
        }
    }
    cloud->width = cloud->points.size();
    cloud->height = 1;
    
    pcl::PointXYZ pmin, pmax;
    double diagonal = pcl::getMaxSegment(*cloud, pmin, pmax);
    
    std::cout << "点云数量: " << cloud->points.size() << std::endl;
    std::cout << "包围盒对角线长度: " << diagonal << std::endl;
    std::cout << "理论对角线长度 (√(10²+10²+10²)): " 
              << std::sqrt(10*10 + 10*10 + 10*10) << std::endl;
}

int main()
{
    example_full_cloud();
    example_with_indices();
    example_bounding_box_diagonal();
    
    return 0;
}

4.5 特殊情况处理

代码中有一个重要的边界情况处理:

const auto token = std::numeric_limits<std::size_t>::max();
std::size_t i_min = token, i_max = token;

// ... 搜索过程 ...

if (i_min == token || i_max == token)
    return (max_dist = std::numeric_limits<double>::min());

这段代码处理什么情况?

  • 空点云或只有一个点的情况
  • 所有点重合的极端情况
  • 返回最小double值作为错误标志

4.6 性能优化技巧

虽然算法是O(n²),但有一些优化策略:

#include <pcl/common/distances.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>

// 优化策略1: 下采样后再计算
void optimized_getMaxSegment()
{
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>);
    
    // 假设有大量点
    // ... 填充cloud ...
    
    // 先下采样减少点数
    pcl::VoxelGrid<pcl::PointXYZ> vg;
    vg.setInputCloud(cloud);
    vg.setLeafSize(0.01f, 0.01f, 0.01f);  // 1cm体素
    vg.filter(*cloud_filtered);
    
    // 在下采样后的点云上计算
    pcl::PointXYZ pmin, pmax;
    double max_length = pcl::getMaxSegment(*cloud_filtered, pmin, pmax);
    
    std::cout << "原始点数: " << cloud->size() << std::endl;
    std::cout << "下采样后: " << cloud_filtered->size() << std::endl;
    std::cout << "最大线段: " << max_length << std::endl;
}

// 优化策略2: 使用凸包
// 最大线段必然在凸包的顶点之间
void convex_hull_optimization()
{
    // 提示: 可以先计算凸包,然后只在凸包顶点上执行getMaxSegment
    // 这样可以大幅减少需要比较的点数
    std::cout << "提示: 结合pcl::ConvexHull可进一步优化" << std::endl;
}

4.7 在PCL中的实际应用

应用场景1: 自动缩放/归一化

// 将点云归一化到单位立方体
void normalize_point_cloud(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud)
{
    pcl::PointXYZ pmin, pmax;
    double max_extent = pcl::getMaxSegment(*cloud, pmin, pmax);
    
    // 计算中心点
    float cx = (pmin.x + pmax.x) / 2.0f;
    float cy = (pmin.y + pmax.y) / 2.0f;
    float cz = (pmin.z + pmax.z) / 2.0f;
    
    // 归一化
    for (auto& pt : cloud->points) {
        pt.x = (pt.x - cx) / max_extent;
        pt.y = (pt.y - cy) / max_extent;
        pt.z = (pt.z - cz) / max_extent;
    }
}

应用场景2: 估计采样分辨率

// 根据点云大小自动设置采样参数
void auto_sampling_resolution(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud)
{
    pcl::PointXYZ pmin, pmax;
    double extent = pcl::getMaxSegment(*cloud, pmin, pmax);
    
    // 根据点云大小设置体素大小(例如1/100的extent)
    float voxel_size = extent / 100.0f;
    
    std::cout << "建议的体素大小: " << voxel_size << std::endl;
}

应用场景3: 初始配准估计

// ICP配准前的粗略尺度估计
void estimate_scale_for_registration(
    pcl::PointCloud<pcl::PointXYZ>::Ptr source,
    pcl::PointCloud<pcl::PointXYZ>::Ptr target)
{
    pcl::PointXYZ s_min, s_max, t_min, t_max;
    double source_extent = pcl::getMaxSegment(*source, s_min, s_max);
    double target_extent = pcl::getMaxSegment(*target, t_min, t_max);
    
    double scale_ratio = target_extent / source_extent;
    std::cout << "源点云和目标点云的尺度比: " << scale_ratio << std::endl;
    
    // 可用于调整ICP的距离阈值
    double icp_threshold = source_extent * 0.01;  // 1%的extent
}

4.8 与其他PCL函数的配合使用

#include <pcl/common/distances.h>
#include <pcl/common/centroid.h>
#include <pcl/common/transforms.h>

// 综合示例: 点云预处理流程
void preprocessing_pipeline(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud)
{
    // 1. 计算质心
    Eigen::Vector4f centroid;
    pcl::compute3DCentroid(*cloud, centroid);
    
    // 2. 计算最大范围
    pcl::PointXYZ pmin, pmax;
    double max_extent = pcl::getMaxSegment(*cloud, pmin, pmax);
    
    // 3. 中心化并归一化
    Eigen::Affine3f transform = Eigen::Affine3f::Identity();
    transform.translation() << -centroid[0], -centroid[1], -centroid[2];
    
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_transformed(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::transformPointCloud(*cloud, *cloud_transformed, transform);
    
    // 缩放到单位尺度
    for (auto& pt : cloud_transformed->points) {
        pt.x /= max_extent;
        pt.y /= max_extent;
        pt.z /= max_extent;
    }
    
    std::cout << "点云已中心化并归一化到单位尺度" << std::endl;
}

五、欧氏距离函数

5.1 平方欧氏距离 (squaredEuclideanDistance)

5.1.1 通用版本(3D点)
template<typename PointType1, typename PointType2> inline float
squaredEuclideanDistance (const PointType1& p1, const PointType2& p2)
{
    float diff_x = p2.x - p1.x, diff_y = p2.y - p1.y, diff_z = p2.z - p1.z;
    return (diff_x*diff_x + diff_y*diff_y + diff_z*diff_z);
}

特点:

  • 模板函数,支持不同点类型之间的距离计算
  • 计算3D点的平方距离
  • 返回float类型
5.1.2 特化版本(2D点 - PointXY)
template<> inline float
squaredEuclideanDistance (const PointXY& p1, const PointXY& p2)
{
    float diff_x = p2.x - p1.x, diff_y = p2.y - p1.y;
    return (diff_x*diff_x + diff_y*diff_y);
}

特点:

  • 专门为2D点(PointXY)优化的版本
  • 只计算x和y方向的距离
  • 模板特化(template specialization)

5.2 欧氏距离 (euclideanDistance)

template<typename PointType1, typename PointType2> inline float
euclideanDistance (const PointType1& p1, const PointType2& p2)
{
    return (std::sqrt (squaredEuclideanDistance (p1, p2)));
}

特点:

  • 基于squaredEuclideanDistance实现
  • 返回真实的欧氏距离(开方后)
  • 性能略低于平方距离(多了sqrt运算)

5.3 完整使用示例

#include <pcl/common/distances.h>
#include <pcl/point_types.h>
#include <iostream>
#include <vector>

// 示例1: 基本距离计算
void basic_distance_calculation()
{
    std::cout << "=== 示例1: 基本距离计算 ===" << std::endl;
    
    // 3D点距离
    pcl::PointXYZ p1(1.0f, 2.0f, 3.0f);
    pcl::PointXYZ p2(4.0f, 6.0f, 8.0f);
    
    float dist_sqr = pcl::squaredEuclideanDistance(p1, p2);
    float dist = pcl::euclideanDistance(p1, p2);
    
    std::cout << "点1: (" << p1.x << ", " << p1.y << ", " << p1.z << ")" << std::endl;
    std::cout << "点2: (" << p2.x << ", " << p2.y << ", " << p2.z << ")" << std::endl;
    std::cout << "平方距离: " << dist_sqr << std::endl;
    std::cout << "欧氏距离: " << dist << std::endl;
    
    // 验证
    float dx = p2.x - p1.x;
    float dy = p2.y - p1.y;
    float dz = p2.z - p1.z;
    float verify = std::sqrt(dx*dx + dy*dy + dz*dz);
    std::cout << "验证: " << verify << std::endl;
}

// 示例2: 2D点距离(PointXY特化版本)
void point_xy_distance()
{
    std::cout << "\n=== 示例2: 2D点距离 ===" << std::endl;
    
    pcl::PointXY p1, p2;
    p1.x = 0.0f; p1.y = 0.0f;
    p2.x = 3.0f; p2.y = 4.0f;
    
    float dist_sqr = pcl::squaredEuclideanDistance(p1, p2);
    float dist = pcl::euclideanDistance(p1, p2);
    
    std::cout << "2D点1: (" << p1.x << ", " << p1.y << ")" << std::endl;
    std::cout << "2D点2: (" << p2.x << ", " << p2.y << ")" << std::endl;
    std::cout << "平方距离: " << dist_sqr << std::endl;
    std::cout << "欧氏距离: " << dist << " (应该是5.0)" << std::endl;
}

// 示例3: 不同点类型之间的距离
void mixed_point_types()
{
    std::cout << "\n=== 示例3: 混合点类型 ===" << std::endl;
    
    pcl::PointXYZ p1(1.0f, 2.0f, 3.0f);
    pcl::PointXYZRGB p2;
    p2.x = 4.0f; p2.y = 5.0f; p2.z = 6.0f;
    p2.r = 255; p2.g = 0; p2.b = 0;  // 颜色信息不影响距离计算
    
    // 模板函数可以处理不同类型的点
    float dist = pcl::euclideanDistance(p1, p2);
    std::cout << "PointXYZ 和 PointXYZRGB 之间的距离: " << dist << std::endl;
}

// 示例4: 性能比较 - 何时使用平方距离
void performance_comparison()
{
    std::cout << "\n=== 示例4: 性能考虑 ===" << std::endl;
    
    pcl::PointXYZ p1(0.0f, 0.0f, 0.0f);
    
    // 场景: 找到距离阈值内的点
    float threshold = 5.0f;
    float threshold_sqr = threshold * threshold;  // 25.0
    
    std::vector<pcl::PointXYZ> points;
    for (int i = 0; i < 10; ++i) {
        points.push_back(pcl::PointXYZ(i * 1.0f, i * 0.5f, i * 0.3f));
    }
    
    // ✅ 高效方式: 使用平方距离
    std::cout << "使用平方距离判断(推荐):" << std::endl;
    for (size_t i = 0; i < points.size(); ++i) {
        float dist_sqr = pcl::squaredEuclideanDistance(p1, points[i]);
        if (dist_sqr < threshold_sqr) {
            std::cout << "  点" << i << " 在阈值内, 平方距离=" << dist_sqr << std::endl;
        }
    }
    
    // ❌ 低效方式: 使用欧氏距离(多余的sqrt)
    std::cout << "使用欧氏距离判断(不推荐):" << std::endl;
    for (size_t i = 0; i < points.size(); ++i) {
        float dist = pcl::euclideanDistance(p1, points[i]);
        if (dist < threshold) {
            std::cout << "  点" << i << " 在阈值内, 距离=" << dist << std::endl;
        }
    }
}

int main()
{
    basic_distance_calculation();
    point_xy_distance();
    mixed_point_types();
    performance_comparison();
    
    return 0;
}

5.4 何时使用平方距离 vs 欧氏距离

使用平方距离的场景(推荐):

// 1. 距离比较(不需要真实距离值)
if (pcl::squaredEuclideanDistance(p1, p2) < pcl::squaredEuclideanDistance(p1, p3)) {
    // p2离p1更近
}

// 2. 阈值判断
float threshold = 0.1f;
float threshold_sqr = threshold * threshold;
if (pcl::squaredEuclideanDistance(query, candidate) < threshold_sqr) {
    // 在阈值内
}

// 3. 最近邻搜索
float min_dist_sqr = std::numeric_limits<float>::max();
int nearest_idx = -1;
for (size_t i = 0; i < cloud->size(); ++i) {
    float d = pcl::squaredEuclideanDistance(query, cloud->points[i]);
    if (d < min_dist_sqr) {
        min_dist_sqr = d;
        nearest_idx = i;
    }
}

使用欧氏距离的场景:

// 1. 需要报告真实距离值
float actual_distance = pcl::euclideanDistance(p1, p2);
std::cout << "两点相距 " << actual_distance << " 米" << std::endl;

// 2. 需要距离的数学运算(如加权)
float weight = 1.0f / pcl::euclideanDistance(query, neighbor);

// 3. 可视化或用户界面显示

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

3D视觉算法开发

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值