我目前正在尝试使用一些扩展boost::geometry多边形附加信息。但是编译器开始#include <boost/geometry.hpp>namespace bg = boost::geometry;using point_t = bg::model::d2::point_xy<double>;using polygon_t = bg::model::polygon<point_t>;using mpolygon_t = bg::model::multi_polygon<polygon_t>;using taggedPolygon_t = std::tuple<polygon_t, void*>;using multiTaggedPolygon_t = bg::model::multi_polygon<taggedPolygon_t>;void foo(){ mpolygon_t poly; // OK taggedPolygon_t taggedPoly; // OK mpolygon_t mpoly; // OK multiTaggedPolygon_t poly; // Compile error}有人暗示如何正确处理这些东西吗?我的目的是存储一些其他信息,并将其附加到多边形上,以备后用。我还尝试使用继承而不是std::tuple:struct taggedPolygon_t : bg::model::polygon<point_t>{ void* tag;};namespace boost { namespace geometry { namespace traits{template<> struct tag<taggedPolygon_t> { typedef polygon_tag type; };template<> struct ring_const_type<taggedPolygon_t> { typedef const taggedPolygon_t& type; };template<> struct ring_mutable_type<taggedPolygon_t> { typedef taggedPolygon_t& type; };template<> struct interior_const_type<taggedPolygon_t> { typedef const taggedPolygon_t type; };template<> struct interior_mutable_type<taggedPolygon_t> { typedef taggedPolygon_t type; };template<> struct exterior_ring<taggedPolygon_t> { typedef const taggedPolygon_t type; };template<> struct interior_rings<taggedPolygon_t> { typedef const taggedPolygon_t type; };} } } // namespace boost::geometry::traits但是问题仍然存在。 最佳答案 taggedPolygon_t taggedPoly; // OK显然还可以。它只是声明一个元组对象。元组对模板参数没有任何限制。 multiTaggedPolygon_t poly; // Compile error那不行,因为它定义了multi_polugon 实例。该类型确实对模板参数类型提出了概念要求:它必须模型the Polygon concept。元组不满足那些要求。定义多边形概念定义如下:必须存在traits::tag的特殊化,将polygon_tag定义为类型必须是traits::ring_type的特殊化,将其外圈和内圈的类型定义为类型由ring_type定义的此类型必须满足Ring Concept 必须是traits::interior_type的特殊化,它将其内部环的集合的类型定义为type;此集合本身必须满足Boost.Range随机访问范围概念必须是traits::exterior_ring的特殊化,它有两个名为get,的函数返回外环,一个是const,另一个是非const 必须是traits::interior_rings的特化,它有两个名为get,的函数返回内环,一个是const,另一个是非const 因此,在这里让我们变得又快又脏: Note, the docs seem to be slightly out of sync w.r.t. the mutable/const distinction.namespace boost::geometry::traits { template <typename Underlying, typename Tag> struct ring_mutable_type<taggedGeometry<Underlying, Tag> > : ring_mutable_type<Underlying> {}; template <typename Underlying, typename Tag> struct ring_const_type<taggedGeometry<Underlying, Tag> > : ring_const_type<Underlying> {}; template <typename Underlying, typename Tag> struct interior_mutable_type<taggedGeometry<Underlying, Tag> > : interior_mutable_type<Underlying> {}; template <typename Underlying, typename Tag> struct interior_const_type<taggedGeometry<Underlying, Tag> > : interior_const_type<Underlying> {}; template <typename Underlying, typename Tag> struct tag<taggedGeometry<Underlying, Tag> > : tag<Underlying> {}; template <typename Underlying, typename Tag> struct exterior_ring<taggedGeometry<Underlying, Tag> > : exterior_ring<Underlying> {}; template <typename Underlying, typename Tag> struct interior_rings<taggedGeometry<Underlying, Tag> > : interior_rings<Underlying> {};}现在您可以编译您的声明。 Live On Coliru mpolygon_t mpoly; // OKmultiTaggedPolygon_t poly; // OKstatic_assert(std::is_same_v<bg::ring_type<mpolygon_t>::type, bg::ring_type<multiTaggedPolygon_t>::type>, "");请注意,我说的是“快速又脏”。因为这还不够。更多...注意我默默地从std::tuple<>更改为一个自定义结构方便。如果不是,则必须使用tuple getter委托(delegate):template <typename Underlying, typename Tag> struct exterior_ring<taggedGeometry<Underlying, Tag> > : exterior_ring<Underlying> { using G = taggedGeometry<Underlying, Tag>; using base = exterior_ring<Underlying>; static decltype(auto) get(G& v) { return base::get(std::get<0>(v)); } static decltype(auto) get(G const& v) { return base::get(std::get<0>(v)); } };template <typename Underlying, typename Tag> struct interior_rings<taggedGeometry<Underlying, Tag> > : interior_rings<Underlying> { using G = taggedGeometry<Underlying, Tag>; using base = interior_rings<Underlying>; static decltype(auto) get(G& v) { return base::get(std::get<0>(v)); } static decltype(auto) get(G const& v) { return base::get(std::get<0>(v)); } };那也可以: Live On Coliru 演示版现在您可以实际使用它了: Live On Coliru int main() { multiTaggedPolygon_t poly; bg::read_wkt("MULTIPOLYGON (((40 40, 20 45, 45 30, 40 40)), " "((20 35, 10 30, 10 10, 30 5, 45 20, 20 35)," "(30 20, 20 15, 20 25, 30 20)))", poly); std::string reason; if (!bg::is_valid(poly, reason)) { std::cout << "Correcting data: " << reason << "\n"; bg::correct(poly); } std::cout << bg::wkt(poly) << " has an area of " << bg::area(poly) << "\n";}打印品:Correcting data: Geometry has wrong orientationMULTIPOLYGON(((40 40,45 30,20 45,40 40)),((20 35,45 20,30 5,10 10,10 30,20 35),(30 20,20 25,20 15,30 20))) has an area of 712.5洞穴注意,在变异/产生算法中不“支持”标记的多边形。例如,如果您将两个多边形相交,则结果将是使用库定义的通用方法重新构建和构建的多边形,这意味着您“丢失”了标签信息。 list 对于后代 Live On Coliru #include <boost/geometry.hpp>#include <boost/geometry/geometries/geometries.hpp>#include <boost/geometry/geometries/point_xy.hpp>#include <boost/geometry/algorithms/area.hpp>#include <iostream>namespace bg = boost::geometry;using point_t = bg::model::d2::point_xy<double>;using polygon_t = bg::model::polygon<point_t>;using mpolygon_t = bg::model::multi_polygon<polygon_t>;template <typename Geo, typename Tag = void*> using taggedGeometry = std::tuple<Geo, Tag>;/* template <typename Geo, typename Tag = void*> struct taggedGeometry : Geo { using Geo::Geo; Tag _tag_data; };*/namespace boost::geometry::traits { template <typename Underlying, typename Tag> struct ring_mutable_type<taggedGeometry<Underlying, Tag> > : ring_mutable_type<Underlying> {}; template <typename Underlying, typename Tag> struct ring_const_type<taggedGeometry<Underlying, Tag> > : ring_const_type<Underlying> {}; template <typename Underlying, typename Tag> struct interior_mutable_type<taggedGeometry<Underlying, Tag> > : interior_mutable_type<Underlying> {}; template <typename Underlying, typename Tag> struct interior_const_type<taggedGeometry<Underlying, Tag> > : interior_const_type<Underlying> {}; template <typename Underlying, typename Tag> struct tag<taggedGeometry<Underlying, Tag> > : tag<Underlying> {}; template <typename Underlying, typename Tag> struct exterior_ring<taggedGeometry<Underlying, Tag> > : exterior_ring<Underlying> { using G = taggedGeometry<Underlying, Tag>; using base = exterior_ring<Underlying>; static decltype(auto) get(G& v) { return base::get(std::get<0>(v)); } static decltype(auto) get(G const& v) { return base::get(std::get<0>(v)); } }; template <typename Underlying, typename Tag> struct interior_rings<taggedGeometry<Underlying, Tag> > : interior_rings<Underlying> { using G = taggedGeometry<Underlying, Tag>; using base = interior_rings<Underlying>; static decltype(auto) get(G& v) { return base::get(std::get<0>(v)); } static decltype(auto) get(G const& v) { return base::get(std::get<0>(v)); } };}using taggedPolygon_t = taggedGeometry<polygon_t>;using multiTaggedPolygon_t = bg::model::multi_polygon<taggedPolygon_t>;int main() { multiTaggedPolygon_t poly; bg::read_wkt("MULTIPOLYGON (((40 40, 20 45, 45 30, 40 40)), " "((20 35, 10 30, 10 10, 30 5, 45 20, 20 35)," "(30 20, 20 15, 20 25, 30 20)))", poly); std::string reason; if (!bg::is_valid(poly, reason)) { std::cout << "Correcting data: " << reason << "\n"; bg::correct(poly); } std::cout << bg::wkt(poly) << " has an area of " << bg::area(poly) << "\n";}
09-25 21:18