у меня есть эта структура c из сторонней библиотеки:
typedef struct Point3d
{
#ifdef __cplusplus
enum{ SIZE = 3 };
typedef double value_type; ///< type export
double& operator[](size_t index) { return vec[index];} ///< random-access
const double& operator[](size_t index) const { return vec[index];} ///< random-access
#endif
double vec[3]; ///< point data, e.g. 0=x,1=y,2=z
void* data; ///< pointer to additional user-defined data
} Point3d;
эта структура используется как массив следующим образом:
Point3d* mypoints = new Point3d[200];
теперь я хочу сопоставить этот массив - в частности, 3 двойных значения, сохраненных в Point3d::vec - с Eigen::Matrix<double, 3, Eigen::Dynamic>. Я делаю это, следуя этому ответу:
https://stackoverflow.com/a/58980755/10825362
что привело к этой функции:
Eigen::Matrix<double, 3, Eigen::Dynamic> exportToEigen(Point3d *points, int size)
{
Eigen::MatrixXd result(size, 3);
constexpr int stride = sizeof(ALG3D_Point3d)/sizeof(double);
Eigen::VectorXd X =
Eigen::Map<Eigen::VectorXd, Eigen::Unaligned, Eigen::InnerStride<stride>>(
&points[0].vec[0], size
);
Eigen::VectorXd Y =
Eigen::Map<Eigen::VectorXd, Eigen::Unaligned, Eigen::InnerStride<stride>>(
&points[0].vec[1], size
);
Eigen::VectorXd Z =
Eigen::Map<Eigen::VectorXd, Eigen::Unaligned, Eigen::InnerStride<stride>>(
&points[0].vec[2], size
);
result << X, Y, Z;
return result.transpose();
}
теперь мне было интересно, можно ли это сделать без временных X, Y, Z Eigen::VectorXd?





Вы можете сопоставить прямо с Eigen::Matrix<double, 3, Eigen::Dynamic, RowMajor>, что позволяет избежать создания промежуточных векторов.
using Mat = Eigen::Matrix<double, 3, Eigen::Dynamic, RowMajor>;
constexpr int Stride = sizeof(ALG3D_Point3d)/sizeof(double);
return Eigen::Map<Mat, Eigen::Unaligned, Eigen::OuterStride<Stride>>;
теперь хочу сопоставить этот массив - в частности, 3 двойных значения, сохраненных в Point3d::vec - с Eigen::Matrix<double, 3, Eigen::Dynamic>
Существует определение типа для Eigen::Matrix<double, 3, Eigen::Dynamic>и других распространенных типов. Вы можете просто написать Eigen::Matrix3Xd, к вашему сведению.
В любом случае, попробуйте это:
using Point3dStride = Eigen::OuterStride<sizeof(Point3d) / sizeof(double)>;
using Point3dMap = Eigen::Map<
Eigen::Matrix3Xd, Eigen::Unaligned, Point3dStride>;
using ConstPoint3dMap = Eigen::Map<
const Eigen::Matrix3Xd, Eigen::Unaligned, Point3dStride>;
Point3dMap exportToEigen(Point3d *points, Eigen::Index size) noexcept
{ return {points->vec, 3 /*rows*/, size}; }
ConstPoint3dMap exportToEigen(const Point3d *points, Eigen::Index size) noexcept
{ return {points->vec, 3 /*rows*/, size}; }
Примечание. При этом создается простая карта, которая ссылается на старые данные, а не на копию. Ваш код сделал копию. Если вы этого хотите, либо присвойте возвращаемое значение Matrix3Xd, либо измените код на это:
Eigen::Matrix3Xd copyToEigen(const Point3d *points, Eigen::Index size) noexcept
{ return ConstPoint3dMap{points->vec, 3 /*rows*/, size}; }
Спасибо! работает отлично, я вообще-то хотел получить ссылку, так что это здорово :)
Я пробовал несколько итераций этого, но всегда выдавал статическую ошибку утверждения из собственного: "YOU_TRIED_CALLING_A_VECTOR_METHOD_ON_A_MATRIX"