2016-06-14 63 views
2

我有下面的代碼,它應該計算兩個矩形之間的歐幾里得距離。我使用GCC 4.7.3編譯和Boost v1.58.0Boost多邊形:用euclidean_distance發佈

#include <iostream> 
#include <cmath> 
#include <boost/polygon/polygon.hpp> 
#include <boost/geometry.hpp> 

namespace gtl = boost::polygon; 
using namespace boost::polygon::operators; 

typedef gtl::rectangle_data<int> LayoutRectangle; 

int main(int argc, char** argv) 
{ 
    LayoutRectangle t(16740130,29759232,16740350,29760652); 
    LayoutRectangle n(16808130,29980632,16808350,29982052); 

    std::cout << gtl::euclidean_distance(t, n) << std::endl; 

    std::cout << gtl::euclidean_distance(t, n, gtl::HORIZONTAL) << " " 
       << gtl::euclidean_distance(t, n, gtl::VERTICAL) << std::endl; 

    std::cout << gtl::square_euclidean_distance(t, n) << std::endl; 
    std::cout << std::sqrt(gtl::square_euclidean_distance(t, n)) << std::endl; 
    std::cout << (int) std::sqrt(gtl::square_euclidean_distance(t, n)) << std::endl; 

    return 0; 
} 

上面的代碼產生了以下的輸出:

38022.6 
67780 219980 
52985328800 
230185 
230185 

正確答案是230185.現在,如果我在euclidean_distance實施去看看()在升壓多邊形庫,我看到:

template <typename rectangle_type, typename rectangle_type_2> 
    typename enable_if< typename gtl_and_3<y_r_edist2, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type, 
                  typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type>::type, 
         typename rectangle_distance_type<rectangle_type>::type>::type 
    euclidean_distance(const rectangle_type& lvalue, const rectangle_type_2& rvalue) { 
    double val = (int)square_euclidean_distance(lvalue, rvalue); 
    return std::sqrt(val); 
    } 

這看起來等同於我的代碼std::sqrt(gtl::square_eclidean_distance(t,n))行這給正確答案(230185)。那麼爲什麼我得到38022.6與gtl::euclidean_distance()?我在這裏沒有看到什麼?

enter image description here

+0

經過一番調查後,它看起來像一個bug。 https://svn.boost.org/trac/boost/ticket/12268 – user4979733

回答

0

貌似內部計算滿溢。 我不認爲這是一個錯誤,該庫與底層(未選中)int類型使用不正確。 (然而,存在這樣我提到在端庫中的不同的錯誤。)

嘗試使用該問題的一個較小的「整數表示」:

例如:

LayoutRectangle t(167402,297592,167404,297607); 
LayoutRectangle n(168082,299806,168084,299821); 

不幸的是,在整數運算中沒有問題的一般解決方案,除了0)使用更高的精度可以爲您購買一些東西,1)縮放問題2)使用多精度,3)使用有理算術和整數部分

浮點的解決方法就是標準化的組件,這是多麼std::absstd::complex<double>工程,以避免浮點溢出)

這是好事,用大整數來表示這個原因幾何問題,但 ,作爲一種解決方法,使用座標最大跨度距離(int)std::sqrt((double)std::numeric_limits<int>::max()/2) = 2^15 = 32768。 這是一個令人驚訝的小數目。

完整代碼:

#include <iostream> 
#include <cmath> 
#include <boost/polygon/polygon.hpp> 
#include <boost/geometry.hpp> 

int main(){ 

namespace gtl = boost::polygon; 
using namespace boost::polygon::operators; 

typedef gtl::rectangle_data<int> LayoutRectangle; 

    LayoutRectangle t(167401,297592,167403,297606); 
    LayoutRectangle n(168081,299806,168083,299820); 

    std::cout << gtl::euclidean_distance(t, n) << std::endl; 

    std::cout << gtl::euclidean_distance(t, n, gtl::HORIZONTAL) << " " 
       << gtl::euclidean_distance(t, n, gtl::VERTICAL) << std::endl; 

    std::cout << gtl::square_euclidean_distance(t, n) << std::endl; 
    std::cout << std::sqrt(gtl::square_euclidean_distance(t, n)) << std::endl; 
    std::cout << (int) std::sqrt(gtl::square_euclidean_distance(t, n)) << std::endl; 

} 

輸出:

2302.1 
678 2200 
5299684 
2302.1 
2302 

這是預期的結果。在代碼


來看,似乎有在庫中的缺陷,而不是因爲它給溢出,而是因爲內部計算被強制轉換爲int,而不是底層通用整數數據類型。這意味着,即使您使用多精度整數,結果也可能會溢出。