(如何)在增强几何中创建自己的多边形类型并使用 multi_polygon 类型?
(How to) Create own polygon type in boost geometry and use multi_polygon type with it?
我目前正在尝试使用一些扩展 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
但问题依旧。
我发现了如何通过继承来实现它(第二个代码片段):
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 bg::model::polygon<point_t>::ring_type& type; };
template<> struct ring_mutable_type<taggedPolygon_t> { typedef bg::model::polygon<point_t>::ring_type& type; };
template<> struct interior_const_type<taggedPolygon_t> { typedef const bg::model::polygon<point_t>::inner_container_type& type; };
template<> struct interior_mutable_type<taggedPolygon_t> { typedef bg::model::polygon<point_t>::inner_container_type& type; };
template<> struct exterior_ring<taggedPolygon_t>
{
static bg::model::polygon<point_t>::ring_type& get(bg::model::polygon<point_t>& p) {return p.outer(); }
static bg::model::polygon<point_t>::ring_type const& get(bg::model::polygon<point_t> const& p) {return p.outer(); }
};
template<> struct interior_rings<taggedPolygon_t>
{
static bg::model::polygon<point_t>::inner_container_type& get(bg::model::polygon<point_t>& p) {return p.inners(); }
static bg::model::polygon<point_t>::inner_container_type const& get(bg::model::polygon<point_t> const& p) {return p.inners(); }
};
} } } // 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
的特化,将其外环和内环的类型定义为 type
- ring_type 定义的这种类型必须满足 Ring Concept
- 必须有一个
traits::interior_type
的特化,将其内部环的集合类型定义为类型;此集合本身必须满足 Boost.Range
随机访问范围概念
- 必须有一个
traits::exterior_ring
的特殊化,有两个名为 get,
的函数返回外环,一个是 const,另一个是非 const
- 必须有一个
traits::interior_rings
的特殊化,有两个名为 get,
的函数返回内环,一个是常量,另一个是非常量
所以让我们在这里快速而肮脏:
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> {};
}
现在您可以编译声明了。
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>, "");
注意我说的是 "quick and dirty"。因为这还不够。
更多...
请注意,我默默地从 std::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)); }
};
这也行: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 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
注意事项
请注意,在 mutating/producing 算法中,标记的多边形不是 "supported"。
例如,如果您将两个多边形相交,结果将是新构造的多边形,并使用库定义的通用方法构建,这意味着您 "lose" 标签信息。
列表
为了子孙后代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";
}
我目前正在尝试使用一些扩展 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
但问题依旧。
我发现了如何通过继承来实现它(第二个代码片段):
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 bg::model::polygon<point_t>::ring_type& type; };
template<> struct ring_mutable_type<taggedPolygon_t> { typedef bg::model::polygon<point_t>::ring_type& type; };
template<> struct interior_const_type<taggedPolygon_t> { typedef const bg::model::polygon<point_t>::inner_container_type& type; };
template<> struct interior_mutable_type<taggedPolygon_t> { typedef bg::model::polygon<point_t>::inner_container_type& type; };
template<> struct exterior_ring<taggedPolygon_t>
{
static bg::model::polygon<point_t>::ring_type& get(bg::model::polygon<point_t>& p) {return p.outer(); }
static bg::model::polygon<point_t>::ring_type const& get(bg::model::polygon<point_t> const& p) {return p.outer(); }
};
template<> struct interior_rings<taggedPolygon_t>
{
static bg::model::polygon<point_t>::inner_container_type& get(bg::model::polygon<point_t>& p) {return p.inners(); }
static bg::model::polygon<point_t>::inner_container_type const& get(bg::model::polygon<point_t> const& p) {return p.inners(); }
};
} } } // 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
的特化,将其外环和内环的类型定义为 type - ring_type 定义的这种类型必须满足 Ring Concept
- 必须有一个
traits::interior_type
的特化,将其内部环的集合类型定义为类型;此集合本身必须满足Boost.Range
随机访问范围概念 - 必须有一个
traits::exterior_ring
的特殊化,有两个名为get,
的函数返回外环,一个是 const,另一个是非 const - 必须有一个
traits::interior_rings
的特殊化,有两个名为get,
的函数返回内环,一个是常量,另一个是非常量
所以让我们在这里快速而肮脏:
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> {};
}
现在您可以编译声明了。
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>, "");
注意我说的是 "quick and dirty"。因为这还不够。
更多...
请注意,我默默地从 std::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)); }
};
这也行: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 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
注意事项
请注意,在 mutating/producing 算法中,标记的多边形不是 "supported"。
例如,如果您将两个多边形相交,结果将是新构造的多边形,并使用库定义的通用方法构建,这意味着您 "lose" 标签信息。
列表
为了子孙后代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";
}