You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

将含双精度数组的自定义结构体映射到Eigen::Matrix,如何移除临时变量?

问题描述

我有一个来自第三方库的C语言结构体:

typedef struct Point3d
{
#ifdef __cplusplus  
  enum{ SIZE = 3 };
  typedef double value_type;                                          ///< type export 
  double&       operator[](size_t index)       { return vec[index];}  ///< random-access
  const double& operator[](size_t index) const { return vec[index];}  ///< random-access
#endif

  double vec[3];        ///< point data, e.g. 0=x,1=y,2=z
  void* data; ///< pointer to additional user-defined data
} Point3d;

该结构体被用作数组,示例如下:

Point3d* mypoints = new Point3d[200];

我需要将这个数组中Point3d::vec的3个双精度值映射到Eigen::Matrix<double, 3, Eigen::Dynamic>。参考现有实现写了如下函数:

Eigen::Matrix<double, 3, Eigen::Dynamic> exportToEigen(Point3d *points, int size)
{
    Eigen::MatrixXd result(size, 3);
    constexpr int stride = sizeof(ALG3D_Point3d)/sizeof(double);

    Eigen::VectorXd X = 
        Eigen::Map<Eigen::VectorXd, Eigen::Unaligned, Eigen::InnerStride<stride>>(
            &points[0].vec[0], size
        );

    Eigen::VectorXd Y = 
        Eigen::Map<Eigen::VectorXd, Eigen::Unaligned, Eigen::InnerStride<stride>>(
            &points[0].vec[1], size
        );

    Eigen::VectorXd Z = 
        Eigen::Map<Eigen::VectorXd, Eigen::Unaligned, Eigen::InnerStride<stride>>(
            &points[0].vec[2], size
        );

    result << X, Y, Z;
    return result.transpose();
}

现在想知道:能否在不使用临时X、Y、Z这些Eigen::VectorXd变量的情况下完成该映射?

解决方案

当然可以直接完成映射,不需要临时变量,以下是两种优化实现:

方案1:直接赋值到矩阵行

Eigen::Matrix<double, 3, Eigen::Dynamic> exportToEigen(Point3d *points, int size)
{
    Eigen::Matrix<double, 3, Eigen::Dynamic> result(3, size);
    constexpr int stride = sizeof(Point3d) / sizeof(double); // 修正原代码中ALG3D_Point3d的拼写错误

    // 直接将映射结果赋值到矩阵对应行
    result.row(0) = Eigen::Map<Eigen::VectorXd, Eigen::Unaligned, Eigen::InnerStride<stride>>(
        &points[0].vec[0], size
    );
    result.row(1) = Eigen::Map<Eigen::VectorXd, Eigen::Unaligned, Eigen::InnerStride<stride>>(
        &points[0].vec[1], size
    );
    result.row(2) = Eigen::Map<Eigen::VectorXd, Eigen::Unaligned, Eigen::InnerStride<stride>>(
        &points[0].vec[2], size
    );

    return result;
}

方案2:利用逗号初始化语法

Eigen::Matrix<double, 3, Eigen::Dynamic> exportToEigen(Point3d *points, int size)
{
    constexpr int stride = sizeof(Point3d) / sizeof(double);

    return (Eigen::Matrix<double, 3, Eigen::Dynamic>() <<
        Eigen::Map<Eigen::VectorXd, Eigen::Unaligned, Eigen::InnerStride<stride>>(&points[0].vec[0], size),
        Eigen::Map<Eigen::VectorXd, Eigen::Unaligned, Eigen::InnerStride<stride>>(&points[0].vec[1], size),
        Eigen::Map<Eigen::VectorXd, Eigen::Unaligned, Eigen::InnerStride<stride>>(&points[0].vec[2], size)
    ).finished().transpose();
}

关键说明

  1. 原代码中ALG3D_Point3d是笔误,需修正为Point3d,才能正确计算步长stride——该值表示两个相邻同维度坐标之间间隔的double元素数,确保映射能正确跳过结构体中的额外数据。
  2. 两种方案都直接将Eigen::Map的结果赋值给目标矩阵的对应部分,避免了临时VectorXd变量的创建,代码更简洁且效率与原实现一致。
  3. 由于原数据的内存布局(每个点的XYZ连续存储,且点之间包含额外指针数据)与Eigen::Matrix<double,3,Dynamic>的布局不匹配,无法通过单一映射完成整个矩阵的视图创建,分维度处理是最优的无临时变量方案。

内容的提问来源于stack exchange,提问作者IjonTichy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 03:10:58