5

LineSegment<T,dim>テンプレート化されたクラスで2つの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の質問ではなく、テンプレートに関連している場合は、少し説明していただければ幸いです。

4

2 に答える 2

5

まず、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
于 2013-03-18T18:47:11.243 に答える
0

完全を期すために、完全に仕事をした@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>() );
}
于 2013-03-20T01:14:21.307 に答える