Is it easy to convert between different geometry classes in C ++?

I work in robotics, which means that I use a large number of open source projects related to 3D geometry. Since classes and math tend to be fairly simple, everyone seems to implement their own version of Vector3D, Quaternion, etc., each with slight variations, for example. vec.x, vec.X, vec.x (). Therefore, within the framework of one project, conversion between Eigen, ROS, Assimp, Bullet and other versions of the same base classes may be required. Is there a simple or elegant way to do this in C ++ that does not require n ^ 2 mapping from each library to every other library?

Similarly: This question is SO , but I cannot edit any of the source libraries.

Example:

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

EDIT : If there are ~ 10 different geometry libraries, a particular project can use only 2-4 of them, so I would like to avoid introducing a dependency on all unused libraries. I was hoping for something like static_cast<b::Vec>(a::Vec)or maybe

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

but my understanding of patterns and type_traits is pretty weak.

+4
source share
3 answers

If you create three auxiliary functions for each type of vectors to access X, Yand Z:

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

then you can easily write template functions that work with any type. eg:

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

.

+3

, operator+, " " :

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

.

, Vector a b, , :

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, :

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

I see this is an old question, but check out Boost QVM.

+1
source

Source: https://habr.com/ru/post/1613549/


All Articles