2015-07-08 2 views
1

У меня проблема с boost :: geomentry.Boost, geometry

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

Если я использую подталкивание (1_58) выход - это не правильно, но если я использую подталкивание (1_55 или 1_52), выход - это правильно.



Ожидаемое

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

Результат (повышение 1_58)

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

+1

могли бы заботиться, чтобы добавить, что вы Ожидайте (и что вы получите). Не у всех из нас есть «древние» установки Boost. – WorldSEnder

+0

Вы должны использовать целые значения. Взгляните на http://stackoverflow.com/questions/20080868/segmentation-fault-with-boostpolygon/20081230#20081230 –

+0

Возможно, вы имели в виду square1 there (the eps-ed poly?) – sehe

ответ

1

Вы должны использовать интегральные координаты.

Из документации: http://www.boost.org/doc/libs/1_58_0/libs/polygon/doc/index.htm

координат типа данных является параметром шаблона всех типов данных и алгоритмов, предоставляемых библиотекой, и, как ожидается, будет интегралом. Типы данных координат с плавающей запятой не поддерживаются алгоритмами , реализованными в библиотеке, из-за того, что для достижения устойчивости с плавающей точкой подразумевается другой набор алгоритмов и, как правило, допуски на платформе относительно плавающих точечных представлений.

То же самое относится к более ранним версиям.

В вашем случае вывод Boost (1_55 или 1_52) верен (случайно).

+0

+1 для адресации сути. Мой ответ был просто любопытством. Это ответ, который нужно принять. – sehe

0

Выход может показаться правильным первым вокруг, но на самом деле это не так, если вы посмотрите внимательнее:

немного рефакторинга образец: 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"; 
} 

который печатает

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

Как вы можете видеть, наивный, натуральный выход может кажется 4.25 в какой-то момент, но фактическое значение хранится 4.25000000000000178 в тот момент.

В зависимости от того, какие требования у вас есть, вы можете быть счастливее с некоторыми типами десятичного представления точности.Как доказательство концепции, здесь та же программа параметрироваться использовать 50-значные десятичные поплавки:

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

который печатает:

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)) 
+0

Я понимаю, что этот ответ не добавляет существенную информацию за пределы существующего ответа. Тем не менее любопытный пример Multiprecision может быть информативным. – sehe

Смежные вопросы