2015-10-28 69 views
4

我在機器人工作,這意味着我使用大量的處理3D幾何的開源項目。由於類和數學通常相當簡單,所以每個人似乎都實現了自己的Vector3D,四元數等版本,每個版本都有輕微的變化,例如, vec.x,vec.X,vec.x()。因此在一個項目中,可能需要在Eigen,ROS,Assimp,Bullet和其他相同基本類的版本之間進行轉換。有沒有一種簡單或優雅的方式在C++中執行此操作,而不需要從每個庫到每個其他庫的n^2映射?在C++中輕鬆轉換不同的幾何類?

類似於: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; 
} 

EDIT: 如果有〜10個不同的幾何形狀庫,一個特定的項目可以僅使用其中的2-4,所以我想避免上引入的依賴所有未使用的庫。我希望這樣的事情static_cast<b::Vec>(a::Vec),也許

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

,但我的模板和type_traits理解是相當薄弱。

+1

選擇一箇中介,並將其轉換爲中間數據。 – jaggedSpire

+0

@arprice如果你不能改變他們三個,考慮爲我的答案添加一個自定義類(一個向量類),它應該擴展你的需求 –

回答

1

那麼,就定義了一個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}; 
} 

而且你的一小段代碼將工作。

編輯

如果你不希望定義一個地獄很多的功能,假設你不能從a和b改變矢量版本,加入這些構造modifiy您的載體類:

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

而且你的代碼snippe T將與申報數千個運營商的工作

EDIT 2

如果你希望你的類型,與圖書館的類型,您可以添加轉換操作符到你的結構,例如,如果你希望你的類型是兼容敞篷Vector中,添加此功能類中:

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

他希望能夠添加矢量而不用做n^2個函數這樣做。 – jaggedSpire

+0

好的,我會編輯答案 –

+0

謝謝。您可能還想告訴OP關於轉換運算符的信息,以便他可以從他的自定義類型中獲取庫的各種類型,但是這比OP更需要OP的推測 – jaggedSpire

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

然後您可以輕鬆地編寫適用於任何類型的模板函數。例如:

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

+0

我喜歡這個答案!對於每個要使用的庫,只需執行輔助函數,其餘部分都是模板化的。但是,不要那些向量支持'operator []' - 那麼幫助者就沒有必要了。 – Walter

0

我看到這是一個老問題,但檢查出Boost QVM。

相關問題