C++ 用 std::vector 初始化 Eigen::vector

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17036818/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 20:51:41  来源:igfitidea点击:

Initialise Eigen::vector with std::vector

c++eigen

提问by Fantastic Mr Fox

I have seen it done before but I cannot remember how to efficiently initialize an Eigen::Vectorof known length with a std::vectorof the same length. Here is a good example:

我以前看过它,但我不记得如何Eigen::Vectorstd::vector相同长度的a有效地初始化已知长度的 a 。这是一个很好的例子:

std::vector<double> v1 = {1.0, 2.0, 3.0};

Eigen::Vector3d v2; // Do I put it like this in here: v2(v1) ?
v2 << v1[0], v1[1], v1[2]; // I know you can do it like this but 
                           // I am sure i have seen a one liner.

I have perused thispage about advanced matrix initialization but there is not a clear explanation of the method to perform this action.

我已经仔细阅读了有关高级矩阵初始化的页面,但没有明确说明执行此操作的方法。

回答by awesoon

According to Eigen Doc, Vectoris a typedef for Matrix, and the Matrix has a constructorwith the following signature:

根据 Eigen Doc,Vector是 Matrix 的 typedef,并且 Matrix 具有具有以下签名的构造函数

Matrix (const Scalar *data)

Constructs a fixed-sized matrix initialized with coefficients starting at data.

Matrix (const Scalar *data)

构造一个固定大小的矩阵,用从 data 开始的系数初始化。

And vector referencedefines the std::vector::dataas:

矢量参考定义std::vector::data为:

std::vector::data

T* data();
const T* data() const;

Returns pointer to the underlying array serving as element storage. The pointer is such that range [data(); data() + size())is always a valid range, even if the container is empty.

std::vector::data

T* data();
const T* data() const;

返回指向用作元素存储的底层数组的指针。指针使得 range[data(); data() + size())始终是有效范围,即使容器为空。

So, you could just pass the vector's data as a Vector3dconstructor parameter:

因此,您可以将向量的数据作为Vector3d构造函数参数传递:

Eigen::Vector3d v2(v1.data());

Also, as of Eigen 3.2.8, the constructor mentioned above defined as:

此外,从 Eigen 3.2.8 开始,上面提到的构造函数定义为:

template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
inline Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>
  ::Matrix(const Scalar *data)
{
  this->_set_noalias(Eigen::Map<const Matrix>(data));
}

As you can see, it also uses Eigen::Map, as noted by @ggael and @gongzhitaao.

如您所见,它也使用Eigen::Map,正如@ggael 和@gongzhitaao 所指出的那样。

回答by gongzhitaao

Just to extend @ggael answer in case others didn't notice it:

只是为了扩展@ggael 的回答,以防其他人没有注意到:

From Quick Reference Guide: Mapping External Array:

快速参考指南:映射外部阵列

float data[] = {1,2,3,4};
Map<Vector3f> v1(data);       // uses v1 as a Vector3f object
Map<ArrayXf>  v2(data,3);     // uses v2 as a ArrayXf object
Map<Array22f> m1(data);       // uses m1 as a Array22f object
Map<MatrixXf> m2(data,2,2);   // uses m2 as a MatrixXf object

回答by Pengyao

I found a better answer by this link:

我通过此链接找到了更好的答案:

https://forum.kde.org/viewtopic.php?f=74&t=94839

https://forum.kde.org/viewtopic.php?f=74&t=94839

Basically first create a pointer to the std vector, and then pass the pointer and length to the constructor using Map.

基本上首先创建一个指向 std 向量的指针,然后使用 Map 将指针和长度传递给构造函数。

This method works with dynamic Vector object in Eigen. While I tried using .data() function from std vector as the first answer suggest, it gives me an error: static assertion failed: YOU_CALLED_A_FIXED_SIZE_METHOD_ON_A_DYNAMIC_SIZE_MATRIX_OR_VECTOR

此方法适用于 Eigen 中的动态 Vector 对象。当我尝试使用 std 向量中的 .data() 函数作为第一个答案建议时,它给了我一个错误:静态断言失败:YOU_CALLED_A_FIXED_SIZE_METHOD_ON_A_DYNAMIC_SIZE_MATRIX_OR_VECTOR

But using this method it works!

但是使用这个方法是有效的!

I just copy and paste the relevant code from the link here:

我只是从这里的链接中复制并粘贴相关代码:

std::vector<double> v(4, 100.0);
double* ptr = &v[0];
Eigen::Map<Eigen::VectorXd> my_vect(ptr, 4);

回答by Mr. White

The following one-liner should be more correct:

下面的单行应该更正确:

std::vector<double> a = {1, 2, 3, 4};
Eigen::VectorXd b = Eigen::Map<Eigen::VectorXd, Eigen::Unaligned>(a.data(), a.size());

回答by Lee David

Here is my simple code that converts between array/vector and Eigen::Vector/Eigen::Matrix.

这是我在数组/向量和 Eigen::Vector/Eigen::Matrix 之间转换的简单代码。

#include <iostream>
#include <vector>
#include <Eigen/Dense>

using namespace std;
using namespace Eigen;

void array2eigenMat();
void eigenMat2array();

void array2eigenVec();
void eigenVec2array();

void vector2eigenMat();
void eigenMat2vector();

void vector2eigenVec();
void eigenVec2vector();
int main()
{
    cout << "hello world" <<endl;
    array2eigenMat();
    eigenMat2array();

    array2eigenVec();
    eigenVec2array();

    vector2eigenMat();
    eigenMat2vector();

    vector2eigenVec();
    eigenVec2vector();
    return 0;
}

void array2eigenMat()
{
    cout << "-------------------------- array2eigenMat  --------------------------" << endl;

    int array[9];
    for (int i = 0; i < 9; ++i) array[i] = i;
    cout << "array = [ "; for (int i = 0; i < 9; ++i) cout << array[i] << " "; cout << "]" << endl;

    cout << "colMajor matrix = \n" << Map<Matrix3i>(array) << endl;                     // map a contiguous array as a column-major matrix
    cout << "rowMajor matrix = \n" << Map<Matrix<int, 3, 3, RowMajor>>(array) << endl;  // map a contiguous array as a row-major matrix


    cout << "stride matrix = \n" << Map<MatrixXi, 0, OuterStride<>>(array, 3, 3, OuterStride<>(2)) << endl;
    //mapping an array while specifying an outer stride. Here, since we're mapping as a column-major matrix, 
    // 'outer stride' means the pointer increment between two consecutive columns


    Map<MatrixXi> eigMat1(array, 3, 3); 
    MatrixXi      eigMat2 = Map<MatrixXi>(array, 3, 3);
    array[0] = 9;

    cout << "eigMat1 matrix = \n"; cout << eigMat1 << endl;
    cout << "eigMat2 matrix = \n"; cout << eigMat2 << endl;
    cout << "---------------------------------------------------------------------" << endl;

}
void eigenMat2array()
{
    cout << "-------------------------- eigenMat2array  --------------------------" << endl;
    Matrix3d eigMat;
    eigMat << 
        1, 2, 3,
        4, 5, 6,
        7, 8, 9;
    cout << "init eigMat = \n";    cout << eigMat << endl;

    double* eigMatptr = eigMat.data();
    cout << "array = [ "; for (int i = 0; i < 9; ++i) cout << eigMatptr[i] << " "; cout << "]" << endl;

    eigMat(0, 0) = 9;
    cout << "array = [ "; for (int i = 0; i < 9; ++i) cout << eigMatptr[i] << " "; cout << "]" << endl;


    double *eigMatptrnew = new double[eigMat.size()];
    Map<MatrixXd>(eigMatptrnew, eigMat.rows(), eigMat.cols()) = eigMat;

    eigMat(2, 2) = 0;
    cout << "init matrix = \n"; cout << eigMat << endl;
    cout << "array = [ "; for (int i = 0; i < 9; ++i) cout << eigMatptr[i] << " "; cout << "]" << endl;
    cout << "---------------------------------------------------------------------" << endl;
}

void array2eigenVec()
{
    cout << "-------------------------- array2eigenVec  --------------------------" << endl;

    int array[9];
    for (int i = 0; i < 9; ++i) array[i] = i;
    cout << "data array = [ "; for (int i = 0; i < 9; ++i) cout << array[i] << " "; cout << "]" << endl;

    Map<VectorXi> eigVec(array, 5);
    cout << "eigen  vector transpose = " << eigVec.transpose() << endl;
    cout << "stride vector transpose = " << Map<VectorXi, 0, InnerStride<2> >(array, 4).transpose() << endl;
    // map an array as a vector, specifying an inner stride, that is, the pointer increment between two consecutive coefficients

    array[0] = 9;
    cout << "eigen  vector transpose = " << eigVec.transpose() << endl;
    cout << "stride vector transpose = " << Map<VectorXi, 0, InnerStride<2> >(array, 4).transpose() << endl;

    cout << "---------------------------------------------------------------------" << endl;
}
void eigenVec2array()
{
    cout << "-------------------------- eigenVec2array  --------------------------" << endl;
    VectorXf eigvec(5);
    eigvec << 0, 1, 2, 3, 4;
    cout << "eigen  vector transpose = " << eigvec.transpose() << endl;

    float *array = new float;
    array = eigvec.data();
    cout << "data array = [ "; for (int i = 0; i < eigvec.size(); ++i) cout << array[i] << " "; cout << "]" << endl;

    eigvec(0) = 9;
    cout << "data array = [ "; for (int i = 0; i < eigvec.size(); ++i) cout << array[i] << " "; cout << "]" << endl;

    array[0] = 5;
    cout << "eigen  vector transpose = " << eigvec.transpose() << endl;

    cout << "---------------------------------------------------------------------" << endl;
}

void vector2eigenMat()
{
    cout << "-------------------------- vector2eigenMat --------------------------" << endl;
    vector<int> stdvec{ 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    Map<Matrix<int, 3, 3, RowMajor>> eigMat1(stdvec.data());
    MatrixXi                         eigMat2 = Map<Matrix<int, 3, 3, RowMajor>>(stdvec.data());

    cout << "eigMat1 matrix = \n"; cout << eigMat1 << endl;
    cout << "eigMat2 matrix = \n"; cout << eigMat2 << endl;

    stdvec[0] = 9;
    cout << "eigMat1 matrix = \n"; cout << eigMat1 << endl;
    cout << "eigMat2 matrix = \n"; cout << eigMat2 << endl;

    cout << "---------------------------------------------------------------------" << endl;
}
void eigenMat2vector()
{
    cout << "-------------------------- eigenMat2vector --------------------------" << endl;
    Matrix3d eigMatCol;
    eigMatCol << 
        1, 2, 3,
        4, 5, 6,
        7, 8, 9;
    cout << "eigen matrix col = \n";    cout << eigMatCol << endl;
    vector<double> stdvec1(eigMatCol.data(), eigMatCol.data() + eigMatCol.size());
    cout << "std   vector1 = ["; for (int i = 0; i < stdvec1.size(); ++i) cout << stdvec1[i] << " "; cout << "]" << endl;

    Matrix<double, 3, 3, RowMajor> eigMatRow = eigMatCol;
    cout << "eigen matrix row = \n";    cout << eigMatCol << endl;
    vector<double> stdvec2(eigMatRow.data(), eigMatRow.data() + eigMatRow.size());
    cout << "std   vector2 = ["; for (int i = 0; i < stdvec2.size(); ++i) cout << stdvec2[i] << " "; cout << "]" << endl;

    cout << "---------------------------------------------------------------------" << endl;
}

void vector2eigenVec()
{
    cout << "-------------------------- vector2eigenVec --------------------------" << endl;
    vector<int> stdvec{ 1, 2, 3, 4, 5 };
    cout << "std   vector = ["; for (int i = 0; i < stdvec.size(); ++i) cout << stdvec[i] << " "; cout << "]" << endl;

    Map<VectorXi> eigVec1(stdvec.data(), stdvec.size());
    VectorXi eigVec2 = Map<VectorXi>(stdvec.data(), stdvec.size());
    cout << "eigen  vector1 transpose = " << eigVec1.transpose() << endl;
    cout << "eigen  vector2 transpose = " << eigVec2.transpose() << endl;
    cout << "stride vector  transpose = " << Map<VectorXi, 0, InnerStride<2> >(stdvec.data(), 2).transpose() << endl;


    stdvec[0] = 9;
    cout << "eigen  vector1 transpose = " << eigVec1.transpose() << endl;
    cout << "eigen  vector2 transpose = " << eigVec2.transpose() << endl;

    cout << "stride vector  transpose = " << Map<VectorXi, 0, InnerStride<2> >(stdvec.data(), 2).transpose() << endl;

    cout << "---------------------------------------------------------------------" << endl;
}
void eigenVec2vector()
{
    cout << "-------------------------- eigenVec2vector --------------------------" << endl;
    VectorXf eigvec(5);
    eigvec << 0, 1, 2, 3, 4;
    cout << "eigen  vector transpose = " << eigvec.transpose() << endl;

    vector<float> stdvec(eigvec.data(), eigvec.data() + eigvec.size());
    cout << "std   vector = ["; for (int i = 0; i < stdvec.size(); ++i) cout << stdvec[i] << " "; cout << "]" << endl;

    eigvec(0) = 5;
    cout << "std   vector = ["; for (int i = 0; i < stdvec.size(); ++i) cout << stdvec[i] << " "; cout << "]" << endl;
    cout << "---------------------------------------------------------------------" << endl;
}

More details are Here.

更多细节在这里