2013-06-11 8 views
34

Widziałem to zrobić wcześniej, ale nie pamiętam, jak skutecznie zainicjować Eigen::Vector znanej długości z std::vector o tej samej długości. Oto dobry przykład:Inicjujący Eigen :: wektor z std :: wektor

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. 

Mam przeglądał this stronę o zaawansowanej inicjalizacji macierzy, ale nie jest jasne wyjaśnienie sposobu wykonywania tej czynności.

+4

Spróbuj 'Eigen :: Vector3D v2 (v1. dane()); '. – soon

+2

'Mapa v2 (v1.data(), 3)' – Akavall

Odpowiedz

38

Według Eigen Doc, Vector jest typedef dla Matrix, a matryca ma constructor z następującym podpisem:

Matrix (const Scalar *data) 

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

I vector reference definiuje std::vector::data jak:

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.

Więc, można po prostu przekazać dane wektorowe jako parametr konstruktora Vector3d:

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

Ponadto, jak z Eigen 3.2.8 konstruktora wspomniano powyżej zdefiniowane jako:

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

Jak widać, również korzysta Eigen::Map, jak zauważył @ggael i @gongzhitaao.

+7

Co więcej, istnieje klasa Map <>, która radzi sobie z surowymi buforami: [doc] (http://eigen.tuxfamily.org/dox-devel /group__TutorialMapClass.html). – ggael

+0

@soon Czy istnieje sposób konwersji typu danych w tym procesie? Na przykład. to nie działa: 'std :: vector v = {1,2,3}; Eigen :: Vector3d eigenVd (v.data()); ' –

+0

@DavidDoria, czy odpowiedź ** gongzhitaao ** zadziała dla ciebie? Nie mogę tego teraz sprawdzić, niestety. – soon

23

Wystarczy przedłużyć @ggael odpowiedź w przypadku innych, nie zauważył go:

Od 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 
+2

OSTRZEŻENIE: jest to fajne, ale także niebezpieczne! Ponieważ obiekt Eigen NIE stworzy własnej pamięci. Będzie działać na pamięci dostarczanej przez "dane". Innymi słowy, praca z obiektem Eigen, gdy obiekt "data" znajdzie się poza zasięgiem, spowoduje błąd segmentacji (lub naruszenie dostępu do pamięci). – Sobi

11

znalazłem lepszą odpowiedź przez ten link:

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

Zasadniczo najpierw utwórz wskaźnik do wektora standardowego, a następnie przekaż wskaźnik i długość do konstruktora przy użyciu mapy.

Ta metoda działa z dynamicznym obiektem Vector w Eigen. Chociaż próbowałem używając .data (funkcji) z std wektora jako pierwsza odpowiedź sugeruje, że daje mi błąd: twierdzenie statyczne nie powiodło się: YOU_CALLED_A_FIXED_SIZE_METHOD_ON_A_DYNAMIC_SIZE_MATRIX_OR_VECTOR

Ale przy użyciu tej metody to działa!

po prostu skopiować i wkleić odpowiedni kod z linku tutaj:

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

Poniżej jedna wkładka powinna być bardziej poprawne:

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

Jeśli 'a' jest zamiast' const std :: vector ', zmień' Eigen :: VectorXd' na 'const Eigen :: VectorXd'. – Thucydides411