(如何)在增强几何图形中创建自己的多边形类型,并对其使用multi_polygon类型? [英] (How to) Create own polygon type in boost geometry and use multi_polygon type with it?
问题描述
我目前正在尝试将boost :: geometry多边形扩展为一些附加信息.但是编译器会启动
I'm currently trying to extend boost::geometry polygons with some additional information. However the compiler starts
#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
}
有人暗示如何正确处理这些东西吗?我的目的是存储一些其他信息,并将其附加到多边形上以供以后使用.
Does anybody have a hint how to get that stuff right? My intent is to store some additional information and attach it to the polygon for later usage.
我也尝试使用继承而不是std :: tuple:
I also tried to use inheritance instead of 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
显然可以.它只是声明一个元组对象.元组对模板参数没有任何限制.
Obviously ok. It just declares a tuple object. Tuples pose no restrictions on the template arguments.
multiTaggedPolygon_t poly; // Compile error
那不行,因为它定义了一个multi_polugon<>实例.该类型确实对模板参数类型提出了概念要求:它必须对
That's not OK, because it defines a multi_polugon<> instance. That type does pose concept requirements on the template argument type: it must model the Polygon concept.
一个元组不满足那些要求.
A tuple does not satisfy those requirements.
多边形概念定义如下:
- 必须有一个专门的
traits :: tag
定义polygon_tag
作为类型 - 必须有一个专门的
traits :: ring_type
定义其外圈和内圈的类型为 - 由ring_type定义的此类型必须满足铃声概念"
- 必须有一个专门的
traits :: interior_type
,将其内环的集合的类型定义为type;此集合本身必须满足Boost.Range
随机访问范围概念 - 必须是
traits :: exterior_ring
的特化,它具有两个名为get的函数,
返回外环,一个是const,另一个是非const - 必须是
traits :: interior_rings
的特化,它具有两个名为get 的函数,它们返回内部环,一个为const,另一个为非const
- there must be a specialization of
traits::tag
definingpolygon_tag
as type - there must be a specialization of
traits::ring_type
defining the type of its exterior ring and interior rings as type - this type defined by ring_type must fulfill the Ring Concept
- there must be a specialization of
traits::interior_type
defining the type of the collection of its interior rings as type; this collection itself must fulfill aBoost.Range
Random Access Range Concept - there must be a specialization of
traits::exterior_ring
with two functions namedget,
returning the exterior ring, one being const, the other being non const - there must be a specialization of
traits::interior_rings
with two functions namedget,
returning the interior rings, one being const, the other being non const
因此,让我们在此快速而肮脏:
So let's be quick and dirty here:
请注意,文档似乎与w.r.t不同步.可变/常量区别.
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> {};
}
现在您可以编译声明了.
Now you can compile your declaration.
mpolygon_t mpoly; // OK
multiTaggedPolygon_t poly; // OK
static_assert(std::is_same_v<bg::ring_type<mpolygon_t>::type, bg::ring_type<multiTaggedPolygon_t>::type>, "");
请注意,我说的是又快又脏".因为这还不够.
Note I said "quick and dirty". Because this isn't enough.
请注意,我默默地将 std :: tuple<>
更改为以下内容的自定义结构方便.如果没有,则必须使用tuple getter委托:
Note I silently changed from std::tuple<>
to a custom struct for
convenience. If not, you'd have to delegate the using the tuple getter:
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)); }
};
这也可以: 在Coliru上直播
现在您可以实际使用它了:
Now you can actually use it:
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 orientation
MULTIPOLYGON(((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
注意事项
请注意,在更改/生成算法中不支持"标记的多边形.
CAVEATS
Note that tagged polygons are not "supported" in mutating/producing algorithms.
例如,如果您将两个多边形相交,则结果将是使用库定义的通用方法重新构建和构建的多边形,这意味着您将丢失"标签信息.
For example, if you intersect two polygons, the result will be polygons freshly constructed and built with the generic methods the library defines, which means you "lose" the tag info.
对于后代 在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";
}
这篇关于(如何)在增强几何图形中创建自己的多边形类型,并对其使用multi_polygon类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!