我希望拥有std::vector
个地理区域的几何图形。其中一些区域是连续的,并由多边形表示。有些区域是不连续的,由多边形表示。我的计划是使用std::vector<boost::variant<polygon,multipolygon>>
来解决这种差异。
polygon
和multipolygon
都符合几何概念,因此我们应该可以在任何一个上调用信封。这样做有效,但我似乎无法在envelope
上致电variant<polygon,multipolygon>
。
#include <vector>
#include <boost/variant.hpp>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/geometries/box.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/geometry/multi/geometries/multi_polygon.hpp>
namespace bg = boost::geometry;
typedef bg::model::point<double, 2, bg::cs::cartesian> point;
typedef bg::model::box<point> box;
typedef bg::model::polygon<point, true, true> polygon; //cw, closed polygon
typedef bg::model::multi_polygon<polygon> multipolygon;
typedef boost::variant<polygon,multipolygon> star_polygon;
int main(void){
polygon staunton_county;
bg::read_wkt("POLYGON ((-79.091666 38.132142, -79.09711 38.184771,"
" -79.02301 38.195777, -79.049779 38.121112, -79.091666 38.132142))",
staunton_county);
multipolygon dickson_county;
bg::read_wkt("MULTIPOLYGON (((-87.151995 36.289037, -87.146906 36.293344,"
" -87.144172 36.292142, -87.142315 36.294607, -87.139332 36.292418,"
" -87.14237199999999 36.290684, -87.151995 36.289037)),"
" ((-87.20424199999999 35.959186, -87.53453 35.993074,"
" -87.56679800000001 36.177857, -87.513533 36.334713,"
" -87.286501 36.321933, -87.17730299999999 36.314145,"
" -87.14987600000001 36.176878, -87.182573 36.049726,"
" -87.20424199999999 35.959186)))",
dickson_county);
box bb;
bg::envelope(staunton_county,bb);
std::cout << bg::dsv(bb) << std::endl;
bg::envelope(dickson_county,bb);;
std::cout << bg::dsv(bb) << std::endl;
star_polygon county;
county = staunton_county;
//bg::envelope(county,bb);
if (county.type() == typeid(polygon)){
bg::envelope(boost::get<polygon>(county),bb);
} else {
bg::envelope(boost::get<multipolygon>(county),bb);
}
std::cout << bg::dsv(bb) << std::endl;
return 0;
}
如果我取消注释行bg::envelope(county,bb);
,编译将失败以下错误:
In file included from variant_envelope.cpp:4:
In file included from /usr/local/include/boost/geometry.hpp:17:
In file included from /usr/local/include/boost/geometry/geometry.hpp:35:
In file included from /usr/local/include/boost/geometry/strategies/strategies.hpp:25:
In file included from /usr/local/include/boost/geometry/strategies/intersection.hpp:22:
In file included from /usr/local/include/boost/geometry/strategies/cartesian/cart_intersect.hpp:21:
In file included from /usr/local/include/boost/geometry/algorithms/detail/assign_values.hpp:29:
In file included from /usr/local/include/boost/geometry/algorithms/append.hpp:24:
In file included from /usr/local/include/boost/geometry/geometries/concepts/check.hpp:33:
/usr/local/include/boost/geometry/algorithms/not_implemented.hpp:64:5: error:
no matching function for call to 'assertion_failed'
BOOST_MPL_ASSERT_MSG
^~~~~~~~~~~~~~~~~~~~
/usr/local/include/boost/mpl/assert.hpp:434:48: note: expanded from macro
'BOOST_MPL_ASSERT_MSG'
#define BOOST_MPL_ASSERT_MSG( c, msg, types_ ) \
^
/usr/local/include/boost/mpl/assert.hpp:428:9: note: expanded from macro '\
BOOST_MPL_ASSERT_MSG_IMPL'
...boost::mpl::assertion_failed<(c)>( BOOST_PP_CAT(mpl_assert_arg,counter)::assert_arg() ) \
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/local/include/boost/mpl/assert.hpp:59:58: note: expanded from macro '\
BOOST_MPL_AUX_ASSERT_CONSTANT'
# define BOOST_MPL_AUX_ASSERT_CONSTANT(T, expr) enum { expr }
^
/usr/local/include/boost/geometry/algorithms/not_implemented.hpp:105:7: note:
in instantiation of template class
'boost::geometry::nyi::not_implemented_error<void, void, void>' requested
here
nyi::not_implemented_error
^
/usr/local/include/boost/geometry/algorithms/envelope.hpp:90:18: note: in
instantiation of template class 'boost::geometry::not_implemented<void,
void, void>' requested here
struct envelope: not_implemented<Tag>
^
/usr/local/include/boost/geometry/algorithms/envelope.hpp:163:15: note: in
instantiation of template class
'boost::geometry::dispatch::envelope<boost::variant<boost::geometry::model::polygon<boost::geometry::model::point<double,
2, boost::geometry::cs::cartesian>, true, true, std::vector, std::vector,
std::allocator, std::allocator>,
boost::geometry::model::multi_polygon<boost::geometry::model::polygon<boost::geometry::model::point<double,
2, boost::geometry::cs::cartesian>, true, true, std::vector, std::vector,
std::allocator, std::allocator>, std::vector, std::allocator>,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_>, void>'
requested here
dispatch::envelope<Geometry>::apply(geometry, mbr);
^
variant_envelope.cpp:44:13: note: in instantiation of function template
specialization
'boost::geometry::envelope<boost::variant<boost::geometry::model::polygon<boost::geometry::model::point<double,
2, boost::geometry::cs::cartesian>, true, true, std::vector, std::vector,
std::allocator, std::allocator>,
boost::geometry::model::multi_polygon<boost::geometry::model::polygon<boost::geometry::model::point<double,
2, boost::geometry::cs::cartesian>, true, true, std::vector, std::vector,
std::allocator, std::allocator>, std::vector, std::allocator>,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_>,
boost::geometry::model::box<boost::geometry::model::point<double, 2,
boost::geometry::cs::cartesian> > >' requested here
bg::envelope(county,bb);
^
/usr/local/include/boost/mpl/assert.hpp:82:5: note: candidate function
[with C = false] not viable: no known conversion from 'boost::mpl::failed
************(boost::geometry::nyi::not_implemented_error<void, void,
void>::THIS_OPERATION_IS_NOT_OR_NOT_YET_IMPLEMENTED::************)(types<void,
void, void>)' to 'typename assert<false>::type'
(aka 'mpl_::assert<false>') for 1st argument
int assertion_failed( typename assert<C>::type );
^
1 error generated.
我不认为这与implicit instantiation of undefined template: Boost Bug or Clang Bug?有关,因为我使用的是升级版1.55.0。
注释行之后的if语句是可行的,但它似乎是一个黑客。有没有办法让它工作而不需要枚举变量中的不同类型?
答案 0 :(得分:5)
您可以使用boost::static_visitor
创建一个用于调度变体的多态函数:
static const envelope_ generic_envelope { };
// ...
generic_envelope(county,bb);
envelope_
定义为:
struct envelope_ : boost::static_visitor<void> {
template <typename... T> //dispatch
void operator()(boost::variant<T...> const& v, box& bb) const {
boost::apply_visitor(boost::bind(*this, ::_1, boost::ref(bb)), v);
}
template <typename T> // relay
void operator()(T const& v, box& bb) const {
bg::envelope(v, bb);
}
};
供将来参考:
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/geometries/box.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/geometry/multi/geometries/multi_polygon.hpp>
#include <boost/variant.hpp>
#include <boost/bind.hpp>
namespace bg = boost::geometry;
typedef bg::model::point<double, 2, bg::cs::cartesian> point;
typedef bg::model::box<point> box;
typedef bg::model::polygon<point, true, true> polygon; //cw, closed polygon
typedef bg::model::multi_polygon<polygon> multipolygon;
typedef boost::variant<polygon,multipolygon> star_polygon;
struct envelope_ : boost::static_visitor<void>
{
template <typename... T> //dispatch
void operator()(boost::variant<T...> const& v, box& bb) const {
boost::apply_visitor(boost::bind(*this, ::_1, boost::ref(bb)), v);
}
template <typename T> // relay
void operator()(T const& v, box& bb) const {
bg::envelope(v, bb);
}
};
int main(void){
static const envelope_ generic_envelope { };
polygon staunton_county;
bg::read_wkt("POLYGON ((-79.091666 38.132142, -79.09711 38.184771,"
" -79.02301 38.195777, -79.049779 38.121112, -79.091666 38.132142))",
staunton_county);
multipolygon dickson_county;
bg::read_wkt("MULTIPOLYGON (((-87.151995 36.289037, -87.146906 36.293344,"
" -87.144172 36.292142, -87.142315 36.294607, -87.139332 36.292418,"
" -87.14237199999999 36.290684, -87.151995 36.289037)),"
" ((-87.20424199999999 35.959186, -87.53453 35.993074,"
" -87.56679800000001 36.177857, -87.513533 36.334713,"
" -87.286501 36.321933, -87.17730299999999 36.314145,"
" -87.14987600000001 36.176878, -87.182573 36.049726,"
" -87.20424199999999 35.959186)))",
dickson_county);
box bb;
bg::envelope(staunton_county,bb);
std::cout << bg::dsv(bb) << std::endl;
bg::envelope(dickson_county,bb);;
std::cout << bg::dsv(bb) << std::endl;
star_polygon county;
county = staunton_county;
generic_envelope(county,bb);
std::cout << bg::dsv(bb) << std::endl;
}