我目前正致力于一个处理几何问题的项目。由于这个项目将在商业上使用,我不能使用像CGAL这样的库。
我目前正在使用不精确类型的boost :: geometry,但我遇到了数字问题。 我试图简单地使用boost :: multiprecision中的精确点类型,但是当我调用boost :: geometry函数时它不会编译。
我发现this page显示了如何使用numeric_adaptor来使用具有确切数字类型的boost :: geometry。但是,它似乎过时了,我无法使其发挥作用。
boost :: geometry可以与精确数字类型一起使用吗?怎么样?
#include <vector>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/segment.hpp>
#include <boost/geometry/algorithms/intersection.hpp>
#include <boost/multiprecision/gmp.hpp>
namespace bg = boost::geometry;
namespace bm = boost::multiprecision;
typedef bg::model::d2::point_xy<bm::mpq_rational> point;
typedef boost::geometry::model::segment<point> segment;
int main(void)
{
point a(0,0);
point b(1,0);
point c(1,1);
point d(0,1);
segment s1(a,c);
segment s2(b,d);
std::vector<point> ip;
bg::intersection(s1, s2, ip); // Doesn't compile
return 0;
}
clang ++ 3.4.2输出:
In file included from boost_geom_intersect.cpp:3:
In file included from /usr/include/boost/geometry.hpp:17:
In file included from /usr/include/boost/geometry/geometry.hpp:36:
In file included from /usr/include/boost/geometry/core/radian_access.hpp:21:
In file included from /usr/include/boost/numeric/conversion/cast.hpp:33:
In file included from /usr/include/boost/numeric/conversion/converter.hpp:14:
/usr/include/boost/numeric/conversion/converter_policies.hpp:187:69: error: cannot convert 'const
boost::multiprecision::detail::expression<boost::multiprecision::detail::divides,
boost::multiprecision::detail::expression<boost::multiprecision::detail::multiply_immediates,
boost::multiprecision::number<boost::multiprecision::backends::gmp_rational, 1>, boost::multiprecision::number<boost::multiprecision::backends::gmp_rational, 1>,
void, void>, boost::multiprecision::number<boost::multiprecision::backends::gmp_rational, 1>, void, void>' to 'result_type' (aka 'double') without a conversion
operator
static result_type low_level_convert ( argument_type s ) { return static_cast<result_type>(s) ; }
^~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/boost/numeric/conversion/detail/converter.hpp:524:32: note: in instantiation of member function
'boost::numeric::raw_converter<boost::numeric::conversion_traits<double, boost::multiprecision::detail::expression<boost::multiprecision::detail::divides,
boost::multiprecision::detail::expression<boost::multiprecision::detail::multiply_immediates,
boost::multiprecision::number<boost::multiprecision::backends::gmp_rational, 1>, boost::multiprecision::number<boost::multiprecision::backends::gmp_rational, 1>,
void, void>, boost::multiprecision::number<boost::multiprecision::backends::gmp_rational, 1>, void, void> > >::low_level_convert' requested here
return RawConverterBase::low_level_convert(s);
^
/usr/include/boost/numeric/conversion/cast.hpp:53:27: note: in instantiation of member function
'boost::numeric::convdetail::non_rounding_converter<boost::numeric::conversion_traits<double,
boost::multiprecision::detail::expression<boost::multiprecision::detail::divides,
boost::multiprecision::detail::expression<boost::multiprecision::detail::multiply_immediates,
boost::multiprecision::number<boost::multiprecision::backends::gmp_rational, 1>, boost::multiprecision::number<boost::multiprecision::backends::gmp_rational, 1>,
void, void>, boost::multiprecision::number<boost::multiprecision::backends::gmp_rational, 1>, void, void> >,
boost::numeric::convdetail::dummy_range_checker<boost::numeric::conversion_traits<double,
boost::multiprecision::detail::expression<boost::multiprecision::detail::divides,
boost::multiprecision::detail::expression<boost::multiprecision::detail::multiply_immediates,
boost::multiprecision::number<boost::multiprecision::backends::gmp_rational, 1>, boost::multiprecision::number<boost::multiprecision::backends::gmp_rational, 1>,
void, void>, boost::multiprecision::number<boost::multiprecision::backends::gmp_rational, 1>, void, void> > >,
boost::numeric::raw_converter<boost::numeric::conversion_traits<double, boost::multiprecision::detail::expression<boost::multiprecision::detail::divides,
boost::multiprecision::detail::expression<boost::multiprecision::detail::multiply_immediates,
boost::multiprecision::number<boost::multiprecision::backends::gmp_rational, 1>, boost::multiprecision::number<boost::multiprecision::backends::gmp_rational, 1>,
void, void>, boost::multiprecision::number<boost::multiprecision::backends::gmp_rational, 1>, void, void> > > >::convert' requested here
return converter::convert(arg);
^
/usr/include/boost/geometry/policies/robustness/segment_ratio.hpp:146:22: note: in instantiation of function template specialization 'boost::numeric_cast<double,
boost::multiprecision::detail::expression<boost::multiprecision::detail::divides,
boost::multiprecision::detail::expression<boost::multiprecision::detail::multiply_immediates,
boost::multiprecision::number<boost::multiprecision::backends::gmp_rational, 1>, boost::multiprecision::number<boost::multiprecision::backends::gmp_rational, 1>,
void, void>, boost::multiprecision::number<boost::multiprecision::backends::gmp_rational, 1>, void, void> >' requested here
: boost::numeric_cast<double>
^
/usr/include/boost/geometry/policies/robustness/segment_ratio.hpp:129:9: note: in instantiation of member function
'boost::geometry::segment_ratio<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational, 1> >::initialize' requested here
initialize();
^
/usr/include/boost/geometry/strategies/cartesian/cart_intersect.hpp:207:33: note: in instantiation of member function
'boost::geometry::segment_ratio<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational, 1> >::assign' requested here
sinfo.robust_ra.assign(robust_da, robust_da0);
^
/usr/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp:114:47: note: in instantiation of function template specialization
'boost::geometry::strategy::intersection::relate_cartesian_segments<boost::geometry::policies::relate::segments_intersection_points<boost::geometry::segment_intersection_points<boost::geometry::model::d2::point_xy<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational,
1>, boost::geometry::cs::cartesian>, boost::geometry::segment_ratio<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational, 1> > > >,
void>::apply<boost::geometry::model::segment<boost::geometry::model::d2::point_xy<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational, 1>,
boost::geometry::cs::cartesian> >,
boost::geometry::model::segment<boost::geometry::model::d2::point_xy<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational, 1>,
boost::geometry::cs::cartesian> >, boost::geometry::detail::no_rescale_policy,
boost::geometry::model::d2::point_xy<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational, 1>, boost::geometry::cs::cartesian> >' requested
here
intersection_return_type is = policy::apply(segment1, segment2,
^
/usr/include/boost/geometry/algorithms/intersection.hpp:51:12: note: in instantiation of function template specialization
'boost::geometry::detail::intersection::intersection_segment_segment_point<boost::geometry::model::d2::point_xy<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational,
1>, boost::geometry::cs::cartesian>
>::apply<boost::geometry::model::segment<boost::geometry::model::d2::point_xy<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational, 1>,
boost::geometry::cs::cartesian> >,
boost::geometry::model::segment<boost::geometry::model::d2::point_xy<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational, 1>,
boost::geometry::cs::cartesian> >, boost::geometry::detail::no_rescale_policy,
std::back_insert_iterator<std::vector<boost::geometry::model::d2::point_xy<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational, 1>,
boost::geometry::cs::cartesian>, std::allocator<boost::geometry::model::d2::point_xy<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational,
1>, boost::geometry::cs::cartesian> > > >, boost::geometry::strategy_intersection<boost::geometry::cartesian_tag,
boost::geometry::model::segment<boost::geometry::model::d2::point_xy<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational, 1>,
boost::geometry::cs::cartesian> >,
boost::geometry::model::segment<boost::geometry::model::d2::point_xy<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational, 1>,
boost::geometry::cs::cartesian> >, boost::geometry::model::d2::point_xy<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational, 1>,
boost::geometry::cs::cartesian>, boost::geometry::detail::no_rescale_policy, void> >' requested here
>::apply(geometry1, geometry2, robust_policy, std::back_inserter(geometry_out), strategy);
^
/usr/include/boost/geometry/algorithms/intersection.hpp:148:12: note: in instantiation of function template specialization
'boost::geometry::dispatch::intersection<boost::geometry::model::segment<boost::geometry::model::d2::point_xy<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational,
1>, boost::geometry::cs::cartesian> >,
boost::geometry::model::segment<boost::geometry::model::d2::point_xy<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational, 1>,
boost::geometry::cs::cartesian> >, boost::geometry::segment_tag, boost::geometry::segment_tag, false>::apply<boost::geometry::detail::no_rescale_policy,
std::vector<boost::geometry::model::d2::point_xy<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational, 1>, boost::geometry::cs::cartesian>,
std::allocator<boost::geometry::model::d2::point_xy<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational, 1>,
boost::geometry::cs::cartesian> > >, boost::geometry::strategy_intersection<boost::geometry::cartesian_tag,
boost::geometry::model::segment<boost::geometry::model::d2::point_xy<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational, 1>,
boost::geometry::cs::cartesian> >,
boost::geometry::model::segment<boost::geometry::model::d2::point_xy<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational, 1>,
boost::geometry::cs::cartesian> >, boost::geometry::model::d2::point_xy<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational, 1>,
boost::geometry::cs::cartesian>, boost::geometry::detail::no_rescale_policy, void> >' requested here
>::apply(geometry1, geometry2, robust_policy, geometry_out, strategy());
^
/usr/include/boost/geometry/algorithms/intersection.hpp:308:21: note: in instantiation of function template specialization
'boost::geometry::resolve_variant::intersection<boost::geometry::model::segment<boost::geometry::model::d2::point_xy<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational,
1>, boost::geometry::cs::cartesian> >,
boost::geometry::model::segment<boost::geometry::model::d2::point_xy<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational, 1>,
boost::geometry::cs::cartesian> >
>::apply<std::vector<boost::geometry::model::d2::point_xy<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational, 1>,
boost::geometry::cs::cartesian>, std::allocator<boost::geometry::model::d2::point_xy<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational,
1>, boost::geometry::cs::cartesian> > > >' requested here
>::template apply
^
boost_geom_intersect.cpp:27:9: note: in instantiation of function template specialization
'boost::geometry::intersection<boost::geometry::model::segment<boost::geometry::model::d2::point_xy<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational,
1>, boost::geometry::cs::cartesian> >,
boost::geometry::model::segment<boost::geometry::model::d2::point_xy<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational, 1>,
boost::geometry::cs::cartesian> >, std::vector<boost::geometry::model::d2::point_xy<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational,
1>, boost::geometry::cs::cartesian>,
std::allocator<boost::geometry::model::d2::point_xy<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational, 1>,
boost::geometry::cs::cartesian> > > >' requested here
bg::intersection(s1, s2, ip); // Doesn't compile
^
1 error generated.
答案 0 :(得分:2)
Boost Geometry被从表达式模板返回的代理类型感到困惑,它期望具体的数字结果:documentation
Multiprecision库有两个不同的部分:
- 支持表达式模板的前端编号,用于处理所有操作符重载,表达式评估优化和代码缩减。
- 一系列实现实际算术运算的后端,只需要符合前端减少的接口要求。
元编程在那里停滞不前。
幸运的是,您只需使用已修改的mpq_rational
来禁用表达式模板:
typedef bm::number<bm::gmp_rational, bm::et_off> my_rational;
这将编译没有问题。
Coliru对此嗤之以鼻,但现在是:http://coliru.stacked-crooked.com/a/232d98bfbb430468
#include <vector>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/segment.hpp>
#include <boost/geometry/algorithms/intersection.hpp>
#include <boost/multiprecision/gmp.hpp>
#include <boost/multiprecision/number.hpp>
namespace bg = boost::geometry;
namespace bm = boost::multiprecision;
typedef bm::number<bm::gmp_rational, bm::et_off> my_rational;
typedef bg::model::d2::point_xy<my_rational > point;
typedef boost::geometry::model::segment<point> segment;
int main(void)
{
point a(0,0);
point b(1,0);
point c(1,1);
point d(0,1);
segment s1(a,c);
segment s2(b,d);
std::vector<point> ip;
bg::intersection(s1, s2, ip); // Doesn't compile
return 0;
}