web-dev-qa-db-fra.com

Initialiser Eigen :: vector avec std :: vector

Je l'ai déjà vu, mais je ne me souviens pas comment initialiser efficacement un Eigen::Vector de longueur connue avec un std::vector de même longueur. Voici un bon exemple:

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.

J'ai parcouru cette page sur l'initialisation avancée de la matrice mais il n'y a pas d'explication claire de la méthode pour effectuer cette action .

37
Fantastic Mr Fox

Selon Eigen Doc, Vector est un typedef pour Matrix, et la matrice a un constructeur avec la signature suivante:

Matrix (const Scalar *data)

Construit une matrice de taille fixe initialisée avec des coefficients à partir des données.

Et référence vectorielle définit le std::vector::data Comme:

std::vector::data

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

Renvoie le pointeur sur le tableau sous-jacent servant de stockage d'éléments. Le pointeur est tel que la plage [data(); data() + size()) est toujours une plage valide, même si le conteneur est vide.

Ainsi, vous pouvez simplement passer les données du vecteur en tant que paramètre constructeur Vector3d:

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

De plus, à partir d'Eigen 3.2.8, le constructeur mentionné ci-dessus défini comme:

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));
}

Comme vous pouvez le voir, il utilise également Eigen::Map, Comme l'ont noté @ggael et @gongzhitaao.

43
awesoon

Juste pour étendre la réponse @ggael au cas où d'autres ne l'auraient pas remarqué:

De Guide de référence rapide: Mappage d'un tableau externe :

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
25
gongzhitaao

J'ai trouvé une meilleure réponse par ce lien:

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

Fondamentalement, créez d'abord un pointeur sur le vecteur std, puis passez le pointeur et la longueur au constructeur à l'aide de Map.

Cette méthode fonctionne avec un objet vectoriel dynamique dans Eigen. Alors que j'essayais d'utiliser la fonction .data () du vecteur std comme le suggère la première réponse, cela me donne une erreur: l'assertion statique a échoué: YOU_CALLED_A_FIXED_SIZE_METHOD_ON_A_DYNAMIC_SIZE_MATRIX_OR_VECTOR

Mais en utilisant cette méthode, cela fonctionne!

Je viens de copier et coller le code correspondant à partir du lien ici:

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

La doublure suivante devrait être plus correcte:

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