从std :: vector <Eigen :: Vector3d>转换为std :: vector <Eigen :: Vector3f>

3
我遇到了一个问题,我想将一个std::vector<Eigen::Vector3d>转换为一个std::vector<Eigen::Vector3f>。 我想知道是否有一种解决方法,不必迭代处理这些点。
// mapping using iteration
std::vector< Eigen::Vector3d> tf{ {1,1,1},{1,1,1},{1,1,1} };
std::vector< Eigen::Vector3f> tf2;
tf2.reserve(tf.size());
std::transform(tf.begin(), tf.end(), std::back_inserter(tf2), [](const Eigen::Vector3d& p) {
    return p.cast<float>();
});

我尝试了一些类似于tf.data()的东西,并尝试了转换,但我没有找到解决方案。我还研究了Eigen::Map<>类,但并没有真正找到解决方案。


4
想想这里实际上正在发生什么。你把一堆双精度数转换成一堆单精度数,这是无法避免迭代所有值的。你可以自己编写代码来进行迭代,也可以找到某些库函数来替你完成迭代,但无论哪种方式,都要进行迭代。如果你已经有一些可行的代码,那就用它吧。 - john
std::transform 可以隐藏迭代。 - Kao
@john 是的,实现就像发布的那样,很好。我以为因为它是一个具有连续数据的向量,并且我们知道元素的大小,所以会有一个魔术函数创建一个视图或使用reinterpret_cast之类的东西,但你完全正确。^^ - Rob
2个回答

3
我认为您所要求的是不可能的。Eigen::Map允许您构建一个Eigen数据结构而无需复制或移动,它仅仅是对现有连续数据的视图(通常来自std::arraystd::vector)。您想要执行的操作——从double类型转换为float类型,这是两种具有不同内存布局的不同类型,必须是显式的操作。您会将向量大小缩小一半。通过对同一数据采用不同的视图方式是不可能实现这一点的。

嘿,谢谢回复。就像我上面发布的那样,我希望有一些类似于reinterpret_cast的神奇函数,但我没有仔细考虑过。 - Rob

0
假设 Vector3dVector3f 不会引入任何填充(这对于 Eigen 支持的所有编译器都是正确的),您可以使用一个 Eigen::Map<const Matrix3Xd>,并将其转换为 .cast<float>() 的目标向量上的 Eigen::Map<Matrix3Xf>
std::vector< Eigen::Vector3d> tf{ {1,1,1},{1,1,1},{1,1,1} };
std::vector< Eigen::Vector3f> tf2(tf.size()); // target needs to be actually allocated

Eigen::Matrix3Xf::Map(tf2[0].data(), 3, tf2.size())
  = Eigen::Matrix3Xd::Map(tf[0].data(), 3, tf.size()).cast<float>();

在即将到来的Eigen 3.4分支中,您还可以使用转换映射上的迭代器,如下所示:

Eigen::Map<Eigen::Matrix3Xd> input(tf[0].data(), 3, tf.size());
std::vector<Eigen::Vector3f> tf2(input.cast<float>().colwise().begin(),
                                 input.cast<float>().colwise().end());

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接