Как изменить размер вектора в Eigen3

Я обертываю два вектора Eigen3 в шаблонную LineSegment<T,dim> учебный класс. Вы можете использовать это так:

typedef LineSegment<double,2> LineSegment2d;
typedef LineSegment<double,3> LineSegment3d;
typedef LineSegment<int,3> LineSegment3i;

Он содержит шаблонный метод для изменения размеров компонентов. Вот обрезанное определение:

template<typename T,int dim>
struct LineSegment
{
public:
template<int newDim>
LineSegment<T,newDim> to() const
{
Eigen::Matrix<T,newDim,1> newp1;
Eigen::Matrix<T,newDim,1> newp2;

// TODO initialise newp1 and newp2 from d_p1 and d_p2

return LineSegment<T,newDim>(newp1, newp2);
}

// ... other members ...

protected:
Eigen::Matrix<T,dim,1> d_p1;
Eigen::Matrix<T,dim,1> d_p2;
}

Итак, мой вопрос, как я могу составить возвращаемое значение, как показано выше? Это должно поддерживать как увеличение, так и уменьшение размера.

Я пытался использовать Eigen3 размер (целое) метод, но не мог заставить его работать, не видя предупреждений о смешивании размеров матрицы.

В конечном итоге это должно сработать:

LineSegment2d ls2d;
LineSegment3d ls3d = ls2d.to<3>(); // increase dim
ls2d = ls3d.to<2>();               // decrease dim

Я относительно новичок в шаблонах C ++ и был бы признателен за пояснения, если это не просто вопрос API, а связан с шаблонами.

4

Решение

Во-первых, Эйген resize Метод перераспределяет память, если новое количество элементов не совпадает со старым, как при увеличении, так и при уменьшении, поэтому в этом случае вы потеряете данные

Следующий метод использует .head<int>(), которая является версией Eigen3 .start<int>()плюс некоторые шаблоны программирования, так что вам не нужно проверять, сжимаетесь ли вы или растете:

#include <Eigen/Core>

template <bool COND, int A, int B>
struct IF
{
enum { val = A };
};

template <int A, int B>
struct IF<false, A, B>
{
enum { val = B };
};

template <int A, int B>
struct MIN : IF<A < B, A, B>
{
};

template <typename T,int dim,int newDim>
Eigen::Matrix<T,newDim,1> to(Eigen::Matrix<T,dim,1> p)
{
Eigen::Matrix<int,newDim,1> newp =
Eigen::Matrix<T,newDim,1>::Zero();

newp.template head< MIN<dim,newDim>::val >() =
p.template head< MIN<dim,newDim>::val >();

return newp;
}

Используя это, следующую программу:

#include <iostream>

int main()
{
Eigen::Vector2i p_2i(1,2);
Eigen::Vector3i p_3i(3,4,5);

std::cout << to<int, 2, 3>(p_2i) << std::endl << std::endl;
std::cout << to<int, 3, 2>(p_3i) << std::endl << std::endl;

}

Дает в качестве вывода:

1
2
0

3
4
4

Другие решения

Для полноты вот решение на месте, с помощью техника @ sgvd который сделал работу отлично:

template<typename T,int dim>
struct LineSegment
{
public:
template<int newDim>
LineSegment<T,newDim> to() const
{
Eigen::Matrix<T,newDim,1> newp1;
Eigen::Matrix<T,newDim,1> newp2;

newp1.template head< MIN<dim,newDim>::val >() = d_p1.template head< MIN<dim,newDim>::val >();
newp2.template head< MIN<dim,newDim>::val >() = d_p2.template head< MIN<dim,newDim>::val >();

return LineSegment<T,newDim>(newp1, newp2);
}

// ... other members ...

protected:
Eigen::Matrix<T,dim,1> d_p1;
Eigen::Matrix<T,dim,1> d_p2;

private:
template <bool COND, int A, int B>
struct IF
{
enum { val = A };
};

template <int A, int B>
struct IF<false, A, B>
{
enum { val = B };
};

template <int A, int B>
struct MIN : IF<A < B, A, B>
{};
}

И модульный тест, который проходит:

TEST (LineSegmentTests, to)
{
EXPECT_EQ ( LineSegment3i(Vector3i(1,2,0), Vector3i(3,4,0)),
LineSegment2i(Vector2i(1,2),   Vector2i(3,4)  ).to<3>() );

EXPECT_EQ ( LineSegment2i(Vector2i(1,2),   Vector2i(4,5)),
LineSegment3i(Vector3i(1,2,3), Vector3i(4,5,6)).to<2>() );

EXPECT_EQ ( LineSegment3i(Vector3i(1,2,3), Vector3i(4,5,6)),
LineSegment3i(Vector3i(1,2,3), Vector3i(4,5,6)).to<3>() );
}
0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector