我在一个模板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 :(得分:4)
首先,如果新元素的数量与旧元素不同,Eigen的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
答案 1 :(得分:0)
为了完整性,这里有解决方案 in situ ,使用@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>() );
}