在c ++中轻松转换不同的几何类?

时间:2015-10-28 19:46:29

标签: c++ casting geometry ros

我在机器人领域工作,这意味着我使用了大量处理3D几何的开源项目。由于类和数学往往相当简单,所以每个人似乎都实现了他们自己的Vector3D,Quaternion等版本,每个版本都有轻微的变化,例如vec.x,vec.X,vec.x()。因此,在一个项目中,可能需要在Eigen,ROS,Assimp,Bullet和相同基本类的其他版本之间进行转换。有没有一种简单或优雅的方法在C ++中执行此操作,并不需要从每个库到每个其他库的n ^ 2映射?

类似于:This SO question,但我无法编辑任何源库。

示例:

namespace a
{
class Vector
{
public:
    double x, y, z;
};
} // namespace a

namespace b
{
class Vector
{
public:
    double X, Y, Z;
};
} // namespace b

namespace c
{
class Vector
{
public:
    double& x() { return mx; }
    double& y() { return my; }
    double& z() { return mz; }
private:
    double mx, my, mz;
};
} // namespace c

int main()
{
    a::Vector va;
    b::Vector vb;
    c::Vector vc = va + vb; // Ideal, but probably unrealistic goal
    return 0;
}

修改: 如果有大约10个不同的几何库,则特定项目可能只使用其中的2-4个,因此我希望避免对所有未使用的库引入依赖关系。我希望有类似static_cast<b::Vec>(a::Vec)或者

的东西
c::Vec vc = my_cvt<c::Vec>(vb + my_cvt<b::Vec>(va));

但我对模板和type_traits的理解相当薄弱。

3 个答案:

答案 0 :(得分:3)

如果为每种矢量类型编写三个辅助函数来访问XYZ

double X(const a::Vector& v) { return v.x; }
double Y(const a::Vector& v) { return v.y; }
double Z(const a::Vector& v) { return v.z; }
double X(const c::Vector& v) { return v.x(); }
double Y(const c::Vector& v) { return v.y(); }
//...

然后您可以轻松编写适用于任何类型的模板函数。 e.g:

template<typename V1, typename V2>
V1 operator+(const V1& v1, const V2& v2) { 
  return {X(v1)+X(v2), Y(v1)+Y(v2), Z(v1)+Z(v2)};
}

template<typename V1, typename V2>
V1 convert(const V2& v) { 
  return {X(v), Y(v), Z(v)};
}

int main() {
  a::Vector va;
  b::Vector vb;
  auto vc = convert<c::Vector>(va + vb);
}

Live demo

答案 1 :(得分:1)

好吧,只需定义operator+功能和您不切实际的目标&#39;会实现:

c::Vector operator+(const a::Vector& a, const b::Vector& b) {
    return {a.x+b.X, a.y+b.Y, a.z+b.Z};
}

您的小代码段就可以了。

修改

如果您不想定义很多功能,并假设您无法从a和b更改Vector版本,请通过添加这些构造函数来修改矢量类:

Vector(a::Vector a) : mx(a.x), my(a.y), mz(a.z) {}
Vector(b::Vector b) : mx(b.X), my(b.Y), mz(b.Z) {}

然后只定义一个只处理c类的运算符:

c::Vector operator+(c::Vector a, c::Vector b) {
    return {a.x()+b.x(), a.y()+b.y(), a.z()+b.z()};
}

您的代码段将用于声明数千个运算符

编辑2

如果您希望类型与图书馆的类型兼容,您可以将转换运算符添加到结构中,例如,如果您希望您的类型可以使用Vector a转换,请在您的类中添加此函数:< / p>

operator a::Vector() const {
    // return a a::Vector from our c::Vector
    return a::Vector{mx, my, mz};
}

答案 2 :(得分:1)

我看到这是一个老问题,但请查看Boost QVM。