2013-06-11 40 views
34

Tôi đã thấy nó được thực hiện trước đây nhưng tôi không thể nhớ cách khởi tạo hiệu quả một số Eigen::Vector có độ dài đã biết với std::vector có cùng độ dài. Dưới đây là một ví dụ điển hình:Khởi tạo Eigen :: vectơ với std :: vector

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. 

Tôi đã đọc kỹ this trang về khởi tạo ma trận tiên tiến nhưng không có một lời giải thích rõ ràng về các phương pháp để thực hiện thao tác này.

+4

Hãy thử 'Eigen :: Vector3d v2 (v1. dữ liệu()); – soon

+2

'Bản đồ v2 (v1.data(), 3)' – Akavall

Trả lời

38

Theo Eigen Đốc, Vector là một typedef cho Matrix, và Matrix có constructor với chữ ký sau đây:

Matrix (const Scalar *data) 

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

vector reference xác định std::vector::data như:

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.

Vì vậy, bạn chỉ có thể chuyển dữ liệu của vectơ dưới dạng thông số hàm xây dựng Vector3d:

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

Ngoài ra, như của Eigen 3.2.8, các nhà xây dựng nêu trên được xác định như sau:

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

Như bạn có thể thấy, nó cũng sử dụng Eigen::Map, như ghi nhận của @ggael và @gongzhitaao.

+7

Và nói chung, có lớp Map <> để xử lý các bộ đệm thô: [doc] (http://eigen.tuxfamily.org/dox-devel /group__TutorialMapClass.html). – ggael

+0

@soon Có cách nào để chuyển đổi loại dữ liệu trong quy trình này không? Ví dụ. điều này không hoạt động: 'std :: vector v = {1,2,3}; Eigen :: Vector3d eigenVd (v.data()); ' –

+0

@DavidDoria, câu trả lời của ** gongzhitaao ** có phù hợp với bạn không? Không thể kiểm tra ngay bây giờ, thật không may. – soon

23

Chỉ cần để mở rộng câu trả lời @ggael trong trường hợp người khác không để ý nó:

Từ 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

CẢNH BÁO: điều này thật tuyệt, nhưng cũng nguy hiểm! Bởi vì đối tượng Eigen sẽ KHÔNG tạo ra bộ nhớ riêng của nó. Nó sẽ hoạt động trên bộ nhớ được cung cấp bởi "dữ liệu". Nói cách khác, làm việc với đối tượng Eigen khi đối tượng "dữ liệu" nằm ngoài phạm vi sẽ dẫn đến lỗi phân đoạn (hoặc vi phạm truy cập bộ nhớ). – Sobi

11

Tôi tìm thấy một câu trả lời tốt hơn bằng cách liên kết này:

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

Về cơ bản đầu tiên tạo một con trỏ tới vectơ std, và sau đó truyền con trỏ và chiều dài cho hàm tạo bằng cách sử dụng Map.

Phương pháp này hoạt động với đối tượng Vector động trong Eigen. Trong khi tôi đã thử sử dụng hàm .data() từ vector std như câu trả lời đầu tiên được đề xuất, nó cho tôi một lỗi: xác nhận tĩnh không thành công: YOU_CALLED_A_FIXED_SIZE_METHOD_ON_A_DYNAMIC_SIZE_MATRIX_OR_VECTOR

Nhưng sử dụng phương pháp này nó hoạt động!

tôi chỉ cần sao chép và dán đoạn mã có liên quan từ các liên kết ở đây:

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

Sau đây một lót nên chính xác hơn:

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

Nếu 'a' thay vì' const std :: vector ', sau đó thay đổi' Eigen :: VectorXd' thành 'const Eigen :: VectorXd'. – Thucydides411