2013-03-18 6 views
3

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

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 resize(int), но не смог заставить его работать, не видя предупреждений о смешении размеров матрицы.

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

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

Я относительно новым для шаблонов C++, и был бы признателен немного объяснений, если это не просто вопрос API и связана с шаблонами.

+0

Какова желаемая семантика изменения размеров? Проецирование на первые координаты и разложение с нулевыми значениями в новых координатах? – us2012

+0

@ us2012, шаблон должен использоваться скорее как часть робототехнической системы, которая в первую очередь будет преобразовывать между сегментами 2D-линии из изображения камеры в 3D-сегменты линии из карты ее окружения. Это преобразование двунаправлено. Я мог бы использовать подклассы, а не typedefs, и добавлять специальные методы 'to3' и' to2', но задавался вопросом, есть ли способ сделать это. Единственный пример, который я видел для изменения размеров массивов, - это векторы с динамическим размером, такие как 'VectorXd'. –

+0

В Eigen2 я считаю, что вы можете использовать '.start <3>()', но я могу ошибаться. –

ответ

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 
+0

Я думал, что могу узнать что-то о шаблонах :) Большое спасибо. –

0

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

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

 Смежные вопросы

  • Нет связанных вопросов^_^