简体   繁体   English

如何在boost :: geometry :: equals算法中覆盖浮点公差?

[英]How to override the floating point tolerance in the boost::geometry::equals algorithm?

I am using the boost geometry library to compare two different polygons. 我正在使用Boost几何库来比较两个不同的多边形。 Specifically, I am using the equals algorithm to see if two polygons are congruent (equal dimensions). 具体来说,我使用的是equals算法 ,看两个多边形是否相等(相等尺寸)。

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. 问题在于算法上的公差太小,两个本应相等的多边形(经过一些浮点运算)不在算法定义的公差内。

I'm almost certain that the library is using std::numeric_limits<double>::epsilon() (~2.22e-16) to establish the tolerance. 我几乎可以确定该库正在使用std::numeric_limits<double>::epsilon() (〜2.22e-16)来建立公差。 I would like to set the tolerance to be larger (say 1.0e-10). 我想将公差设置为更大(例如1.0e-10)。

Any ideas on how to do this? 有关如何执行此操作的任何想法?

EDIT: I've changed the title to reflect the responses in the comments. 编辑:我已经更改标题以反映评论中的回复。 Please respond to the follow-up below: 请回应以下后续行动:

Is it possible to override just the boost::geometry::math::detail::equals<Type,true>::apply function? 是否可以仅覆盖boost::geometry::math::detail::equals<Type,true>::apply函数?

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::geometry::equals算法。

For reference, here is the current code from the boost library: 作为参考,这是boost库中的当前代码:

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

The mentioned code can be found in boost/geometry/util/math.hpp , currently in Boost 1.56 or older (here on GitHub ). 可以在boost/geometry/util/math.hpp找到提到的代码,当前在Boost 1.56或更早的版本中(在GitHub上 )。

There is a free function boost::geometry::math::equals() calling internally boost::geometry::math::detail::equals<>::apply() . 有一个免费的功能boost::geometry::math::equals()内部调用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. 当然,您也可以使用自己的非标准坐标类型并实现所需的运算符或重载上述功能。

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 . 但是...当您认为计算结果错误时,可以考虑描述一个特定情况,以确保此问题不是XY问题 Playing with epsilon might improve the result in some cases but make things worse in other. 在某些情况下,使用epsilon可能会改善结果,但在另一些情况下会使情况更糟。 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版本,编译器等,将很有帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM