简体   繁体   English

升压,几何

[英]Boost, geometry

I have a problem with boost::geomentry. 我对boost :: geomentry有问题。

#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <vector>

int main(){
typedef boost::geometry::model::d2::point_xy<double> TBoostPoint;
typedef boost::geometry::model::polygon<TBoostPoint> TBoostPoly;    
TBoostPoly square, square1;    
square.outer().push_back(TBoostPoint(0.5,4.25));
square.outer().push_back(TBoostPoint(0.5,4.5));
square.outer().push_back(TBoostPoint(1.0,4.5));
square.outer().push_back(TBoostPoint(1.0,4.25));
square.outer().push_back(TBoostPoint(0.5,4.25));    
const double eps[] = {1e-15,1e-15,2e-15,2e-15};    
square.outer().push_back(TBoostPoint(0.5,4.25 + eps[0]));
square.outer().push_back(TBoostPoint(0.5,4.5  + eps[1]));
square.outer().push_back(TBoostPoint(1.0,4.5  + eps[2]));
square.outer().push_back(TBoostPoint(1.0,4.25 + eps[3]));
square.outer().push_back(TBoostPoint(0.5,4.25 + eps[0]));    
boost::geometry::correct(square);
boost::geometry::correct(square1);    
std::vector<TBoostPoly> output;    
boost::geometry::intersection(square,square1,output);    
return 0;    
}

If I use Boost( 1_58 ) output - is not correct, but if I use Boost( 1_55 or 1_52 ), output - is correct. 如果我使用Boost( 1_58 )输出-是不正确的,但是如果我使用Boost( 1_551_52 ),则输出-是正确的。



Expected 预期

{(0.5,4.25),(0.5,4.5),(1.0,4.25),(1.0,4.25),(0.5,4.25)}

Result (boost 1_58 ) 结果(提升1_58

{(0.5,4.25),(0.5,4.5),(1.0,4.25),(1.0,4.25 + 5e-8),(0.5,4.25)}.

You have to use integral coordinates. 您必须使用积分坐标。

From the documentation: http://www.boost.org/doc/libs/1_58_0/libs/polygon/doc/index.htm 从文档中: http : //www.boost.org/doc/libs/1_58_0/libs/polygon/doc/index.htm

The coordinate data type is a template parameter of all data types and algorithms provided by the library, and is expected to be integral. 坐标数据类型是库提供的所有数据类型和算法的模板参数,并且期望是不可或缺的。 Floating point coordinate data types are not supported by the algorithms implemented in the library due to the fact that the achieving floating point robustness implies a different set of algorithms and generally platform specific assumptions about floating point representations. 库中实现的算法不支持浮点坐标数据类型,这是因为以下事实:实现浮点鲁棒性暗示着一组不同的算法,并且通常是有关浮点表示的特定于平台的假设。

Same applies to earlier versions. 同样适用于早期版本。

In your case the output of Boost(1_55 or 1_52) is correct ( by accident ). 在您的情况下,Boost(1_55或1_52)的输出是正确的( 偶然 )。

The output may seem correct the first around, but in fact it isn't if you look closer: 首先,输出看起来似乎是正确的,但实际上,如果仔细看,它不是正确的:

A slightly refactored sample: Live On Coliru 稍微重构的示例: Live On Coliru

#include <boost/geometry.hpp>
#include <boost/geometry/io/io.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/array.hpp>
#include <vector>
#include <iomanip>

namespace bg = boost::geometry;

template <typename C, typename T = typename C::value_type>
    void append(C& container, std::initializer_list<T> init) {
        container.insert(container.end(), init);
    }

int main() {
    typedef bg::model::d2::point_xy<double> TBoostPoint;
    typedef bg::model::polygon<TBoostPoint> TBoostPoly;

    std::vector<TBoostPoly> squares;

    using Eps = boost::array<double, 4>;

    for (auto const& eps : { 
                Eps {{     0,     0,     0,     0 }},
                Eps {{ 1e-15, 1e-15, 2e-15, 2e-15 }},
            })
    {
        TBoostPoly square;
        append(square.outer(), {
             { 0.5,  4.25 + eps[0] },
             { 0.5,   4.5 + eps[1] },
             { 1.0,   4.5 + eps[2] },
             { 1.0,  4.25 + eps[3] },
             { 0.5,  4.25 + eps[0] }
            });

        squares.push_back(std::move(square));
    }

    for (auto& p : squares)
        bg::correct(p);

    std::vector<TBoostPoly> output;
    bg::intersection(squares[0], squares[1], output);

    for (auto& p : output) std::cout << "Output: " << bg::wkt(p) << "\n";
    std::cout << std::fixed << std::setprecision(std::numeric_limits<bg::coordinate_type<TBoostPoint>::type >::max_digits10);
    for (auto& p : output) std::cout << "Output: " << bg::wkt(p) << "\n";
}

Which prints 哪些印刷品

Output: POLYGON((0.5 4.5,1 4.5,1 4.25,0.5 4.25,0.5 4.5))
Output: POLYGON((0.50000000000000000 4.50000000000000000,1.00000000000000000 4.50000000000000000,1.00000000000000000 4.25000000000000178,0.50000000000000000 4.25000004999999970,0.50000000000000000 4.50000000000000000))

As you can see, the naive, natural output may seem to be 4.25 at some point, but the actual value stored is 4.25000000000000178 at that exact moment. 正如你所看到的,天真的,自然的输出似乎4.25 ,在某些时候,但存储的实际值是4.25000000000000178在确切时刻。

Depending on what requirements you have you might be happier with some arbitrary precision decimal representation types. 根据您的要求,您可能会更乐于使用任意精度的十进制表示形式。 As a proof of concept, here's the same program parameterized to use 50-digit decimal floats: 作为概念验证,以下是使用50位十进制浮点数进行参数化的同一程序:

Live On Coliru 生活在Coliru

#include <boost/geometry.hpp>
#include <boost/geometry/io/io.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/array.hpp>
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <vector>
#include <iomanip>

namespace bg  = boost::geometry;
namespace bmp = boost::multiprecision;

template <typename C, typename T = typename C::value_type>
    void append(C& container, std::initializer_list<T> init) {
        container.insert(container.end(), init);
    }

int main() {
    typedef bmp::number<bmp::cpp_dec_float<50>, bmp::et_off> Decimal;
    typedef bg::model::d2::point_xy<Decimal> TBoostPoint;
    typedef bg::model::polygon<TBoostPoint> TBoostPoly;

    std::vector<TBoostPoly> squares;

    using Eps = boost::array<Decimal, 4>;

    for (auto const& eps : { 
                Eps {{     0,     0,     0,     0 }},
                Eps {{ 1e-15, 1e-15, 2e-15, 2e-15 }},
            })
    {
        TBoostPoly square;
        append(square.outer(), {
             { 0.5,  4.25 + eps[0] },
             { 0.5,   4.5 + eps[1] },
             { 1.0,   4.5 + eps[2] },
             { 1.0,  4.25 + eps[3] },
             { 0.5,  4.25 + eps[0] }
            });

        squares.push_back(std::move(square));
    }

    for (auto& p : squares)
        bg::correct(p);

    std::vector<TBoostPoly> output;
    bg::intersection(squares[0], squares[1], output);

    for (auto& p : output) std::cout << "Output: " << bg::wkt(p) << "\n";
    std::cout << std::fixed << std::setprecision(std::numeric_limits<bg::coordinate_type<TBoostPoint>::type >::max_digits10);
    for (auto& p : output) std::cout << "Output: " << bg::wkt(p) << "\n";
}

Which prints: 哪些打印:

Output: POLYGON((0.5 4.5,1 4.5,1 4.25,0.5 4.25,0.5 4.5))
Output: POLYGON((0.50000000000000000000000000000000000000000000000000000000000000000000000000000000 4.50000000000000000000000000000000000000000000000000000000000000000000000000000000,1.00000000000000000000000000000000000000000000000000000000000000000000000000000000 4.50000000000000000000000000000000000000000000000000000000000000000000000000000000,1.00000000000000000000000000000000000000000000000000000000000000000000000000000000 4.25000000000000200000000000000015541079975332215847661437120239003029098500000000,0.50000000000000000000000000000000000000000000000000000000000000000000000000000000 4.25000000000000100000000000000007770539987666107923830718560119501514549200000000,0.50000000000000000000000000000000000000000000000000000000000000000000000000000000 4.50000000000000000000000000000000000000000000000000000000000000000000000000000000))

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

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