如何覆盖 boost::geometry::equals 算法中的浮点容差? [英] How to override the floating point tolerance in the boost::geometry::equals algorithm?

查看:122
本文介绍了如何覆盖 boost::geometry::equals 算法中的浮点容差?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 boost 几何库来比较两个不同的多边形.具体来说,我正在使用 equals algorithm 以查看两个多边形是否全等(相等尺寸).

I am using the boost geometry library to compare two different polygons. Specifically, I am using the equals algorithm to see if two polygons are congruent (equal dimensions).

问题是算法的容差太紧,两个应该全等的多边形(经过一些浮点运算后)不在算法定义的容差范围内.

The problem is that the tolerance on the algorithm is too tight and two polygons that should be congruent (after some floating point operations) are not within the tolerance defined by the algorithm.

我几乎可以肯定该库正在使用 std::numeric_limits<double>::epsilon() (~2.22e-16) 来建立容差.我想将容差设置得更大(比如 1.0e-10).

I'm almost certain that the library is using std::numeric_limits<double>::epsilon() (~2.22e-16) to establish the tolerance. I would like to set the tolerance to be larger (say 1.0e-10).

关于如何做到这一点的任何想法?

Any ideas on how to do this?

我已更改标题以反映评论中的回复.请回复以下跟进:

I've changed the title to reflect the responses in the comments. Please respond to the follow-up below:

是否可以只覆盖 boost::geometry::math::detail::equals::apply 函数?

Is it possible to override just the boost::geometry::math::detail::equals<Type,true>::apply function?

这样我就可以只替换发生浮点比较的代码,而不必重写大部分 boost::geometry::equals 算法.

This way I could replace only the code where the floating point comparison occurs and I wouldn't have to rewrite a majority of the boost::geometry::equals algorithm.

作为参考,这里是来自 boost 库的当前代码:

For reference, here is the current code from the boost library:

template <typename Type, bool IsFloatingPoint>
struct equals
{
    static inline bool apply(Type const& a, Type const& b)
    {
        return a == b;
    }
};

template <typename Type>
struct equals<Type, true>
{
    static inline Type get_max(Type const& a, Type const& b, Type const& c)
    {
        return (std::max)((std::max)(a, b), c);
    }

    static inline bool apply(Type const& a, Type const& b)
    {
        if (a == b)
        {
            return true;
        }

        // See http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.17,
        // FUTURE: replace by some boost tool or boost::test::close_at_tolerance
        return std::abs(a - b) <= std::numeric_limits<Type>::epsilon() * get_max(std::abs(a), std::abs(b), 1.0);
    }
};

推荐答案

上面提到的代码可以在 boost/geometry/util/math.hpp 中找到,目前在 Boost 1.56 或更早版本(在这里GitHub).

The mentioned code can be found in boost/geometry/util/math.hpp, currently in Boost 1.56 or older (here on GitHub).

有一个免费的函数 boost::geometry::math::equals() 在内部调用 boost::geometry::math::detail::equals<>::应用().因此,要更改默认行为,您可以重载此函数或为某些坐标类型或类型专门化结构.请记住,在某些算法中,该类型可能会提升为某种更精确的类型.

There is a free function boost::geometry::math::equals() calling internally boost::geometry::math::detail::equals<>::apply(). So to change the default behavior you could overload this function or specialize the struct for some coordinate type or types. Have in mind that in some algorithms that type may be promoted to some more precise type.

当然,您也可以使用自己的非标准坐标类型并实现所需的运算符或重载上述函数.

Of course you could also use your own, non-standard coordinate type and implement required operators or overload the function mentioned above.

但是...当您认为计算结果错误时,您可能会考虑描述一个特定案例,以确保此问题不是 XY 问题.在某些情况下,使用 epsilon 可能会改善结果,但在其他情况下会使情况变得更糟.如果算法中与比较无关的某些部分可以改进怎么办?那么如果您编写了您正在使用的 Boost.Geometry 版本、编译器等,那将会很有帮助.

But... you might consider describing a specific case when you think that the calculated result is wrong to be sure that this question is not a XY problem. Playing with epsilon might improve the result in some cases but make things worse in other. What if some parts of the algorithm not related to the comparison might be improved? Then it would be helpful if you wrote which version of Boost.Geometry you're using, the compiler, etc.

这篇关于如何覆盖 boost::geometry::equals 算法中的浮点容差?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆