我有一个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;
}
如果我使用Boost(1_58)输出 - 不正确,但如果我使用Boost(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)}.
你必须使用积分坐标。
从文档:http://www.boost.org/doc/libs/1_58_0/libs/polygon/doc/index.htm
坐标数据类型是库提供的所有数据类型和算法的模板参数,并且预期是完整的。由于实现浮点鲁棒性意味着不同的算法集和通常关于浮点表示的平台特定假设,因此库中实现的算法不支持浮点坐标数据类型。
同样适用于早期版本。
在您的情况下,Boost(1_55或1_52)的输出是正确的(偶然)。
第一个输出可能看起来是正确的,但事实上如果你仔细观察它就不是这样:
一个稍微重构的样本: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位十进制浮点数:
#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))