2016-06-14 109 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,而不是底层通用整数数据类型。这意味着,即使您使用多精度整数,结果也可能会溢出。