typecasting Eigen::VectorXd to std::vector
vector<int> vec(mat.data(), mat.data() + mat.rows() * mat.cols());
Converting an Eigen::VectorXd to an std::vector<double>
You are using a constructor syntax for the std::vector
vec
although the vector was already declared. That doesn't work.
There are two efficient possibilities to copy the content of an Eigen::VectorXd
into a std::vector<double>
. You can either construct a new std::vector
vec2
, like this:
vector<double> vec2(firstEvector.data(), firstEvector.data() + firstEvector.size());
or use the previously declared vector vec
and transfer the data from the Eigen::VectorXd
by using Eigen::Map
. But in that case the std::vector
first needs to be resized:
vec.resize(firstEvector.size());
Map<VectorXd>(vec.data(), vec.size()) = firstEvector;
Convert every column of an Eigen::Matrix to an std::vector?
I think the most elegant Solution would be to use Eigen::Map
. In your case you would do it like this:
Eigen::MatrixXf mat(3, 4);
mat << 1.1, 2, 3, 50,
2.2, 2, 3, 50,
3.1, 2, 3, 50;
std::vector<float> vec;
vec.resize(mat.rows());
for(int col=0; col<mat.cols(); col++){
Eigen::Map<Eigen::MatrixXf>(vec.data(), mat.rows(), 1 ) = mat.col(col); }
How to get an Eigen vector from an Eigen matrix column/row?
Eigen Slicing and Indexing is of much use here.
To retrieve an i
-th row vector:
VectorXd V = M(i, all);
To retrieve an i
-th column vector:
VectorXd V = M(all, i);
Initialise Eigen::vector with std::vector
According to Eigen Doc, Vector is a typedef for Matrix, and the Matrix has a constructor with the following signature:
Matrix (const Scalar *data)
Constructs a fixed-sized matrix initialized with coefficients starting at data.
And vector reference defines the std::vector::data
as:
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.
So, you could just pass the vector's data as a Vector3d
constructor parameter:
Eigen::Vector3d v2(v1.data());
Also, as of Eigen 3.2.8, the constructor mentioned above defined as:
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.
merging a collection of `Eigen::VectorXd`s into one large `Eigen::VectorXd`
The comma initializer does not work like that. You have to fully initialize the matrix from that. Instead, allocate a large enough vector and iterate and assign the blocks.
#include <iostream>
#include <vector>
#include <Eigen/Dense>
// http://eigen.tuxfamily.org/dox/group__TopicStlContainers.html
#include <Eigen/StdVector>
EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(Eigen::VectorXd)
int main()
{
// make some random VectorXds
std::vector<Eigen::VectorXd> vOfV;
Eigen::VectorXd first(3);
Eigen::VectorXd second(4);
first << 1,2,3;
second << 4,5,6,7;
vOfV.push_back(first);
vOfV.push_back(second);
int len = 0;
for (auto const &v : vOfV)
len += v.size();
Eigen::VectorXd flattened(len);
int offset = 0;
for (auto const &v : vOfV)
{
flattened.middleRows(offset,v.size()) = v;
offset += v.size();
}
std::cout << flattened << "\n";
}
Fill a std::vector from a row of an Eigen Array / Matrix
Figured it out. The problem is related to storage order, the way how Eigen lays out a two dimensional array in memory. There are two possible layouts: RowMajor
and ColumnMajor
. The default layout is ColumnMajor
, which stores the 2D array elements column-wise.
Knowing this, the weird result I get makes sense. The .row(0).data()
returns the pointer to the first element of the first row. The .row(0).size()
is 4 and .row(0).data() + 4
takes the first 4 elements column-wise: [-1, 0, 0, 0]
. Same argument for the second column which starts at (1, 0) element, and counting 4 elements column-wise leads to [0, 0, 0, 30.57]
.
There are two solutions:
- Make the Array/Matrix layout row-major:
Array<double, 2, Dynamic, RowMajor> arr(2, 6);
arr << 1, 2, 3, 4
5, 6, 7, 8;
vector<double> row1_vec(arr.row(0).data(), arr.row(0).data() + arr.cols());
// row1_vec: 1, 2, 3, 4
- or use Eigen's Map class:
Array2Xd arr(2, 4);
arr << 1, 2, 3, 4,
5, 6, 7, 8;
vector<double> row1_vec(arr.cols());
Map<RowVectorXd>(&row1_vec[0], 1, arr.cols()) = arr.row(0);
// row1_vec: 1, 2, 3, 4
Related Topics
C++ Cannot Convert from Base a to Derived Type B via Virtual Base A
Calling Function Template Specialization Using C Calling Conventions
How Does Qt Delete Objects? and How to Store Qobjects
How to Access a Global Variable Within a Local Scope
How to Declare Array with Auto
C++11 Scope Exit Guard, a Good Idea
Convert First Letter in String to Uppercase
Is Begin() == End() for Any Empty() Vector
Sse-Copy, Avx-Copy and Std::Copy Performance
How to Install Tensorflow on Windows
How to Use a Lambda Expression as a Template Parameter
Reshaping a 1-D Array to a Multidimensional Array
Efficiency of Postincrement V.S. Preincrement in C++