(如何)在增强几何图形中创建自己的多边形类型,并对其使用multi_polygon类型? [英] (How to) Create own polygon type in boost geometry and use multi_polygon type with it?

查看:53
本文介绍了(如何)在增强几何图形中创建自己的多边形类型,并对其使用multi_polygon类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在尝试将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 defining polygon_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 a Boost.Range Random Access Range Concept
  • there must be a specialization of traits::exterior_ring with two functions named get, returning the exterior ring, one being const, the other being non const
  • there must be a specialization of traits::interior_rings with two functions named get, 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.

在Coliru上直播

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:

在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

注意事项

请注意,在更改/生成算法中不支持"标记的多边形.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆