c++boostpolygonboost-polygon

How to convert a polygon_set_data in boost::polygon to polygon_data?


First, I mean boost::polygon library, not boost::geometry library. My code is:

namespace gtl = boost::polygon;
using namespace boost::polygon::operators;
typedef gtl::polygon_90_data<int> Polygon;
typedef gtl::polygon_traits<Polygon>::point_type Point;
typedef gtl::polygon_90_set_data<int> PolygonSet;
Point pts1[] = { Point(10000, 20000), Point(12000, 20000), Point(12000, 14000), Point(10000, 14000)};
Polygon poly1;
gtl::set_points(poly1, pts1, pts1 + 4);

Point pts2[] = { Point(11500, 18000), Point(11500, 25000), Point(14000, 25000), Point(14000, 18000)};
Polygon poly2;
gtl::set_points(poly2, pts2, pts2 + 4);

PolygonSet polyset;
assign(polyset, poly1 + poly2);

I want to use the union of poly1 and poly2, it will be a polygon with 8 points. Now I have to convert the result polyset to Polygon type, but I did not find a way to do this. Anyone can tell me how can I do this?


Solution

  • The union of two polygons isn't strictly always a single polygon (what if they were disjunct to begin with).

    If you know this to be the case, I'd suggest just getting the first polygon of the set (perhaps asserting that the set has size 1).

    std::vector<Polygon> v;
    polyset.get_polygons(v);
    if (v.size() == 1) {
        std::cout << "Union was: ";
        Polygon p = std::move(v.front()); // attempt to prevent copying
        for (auto& pt : p)
            std::cout << "{" << pt.x() << ", " << pt.y() << "} ";
    } else {
        std::cout << "Something not quite right here\n";
    }
    

    See it Live On Coliru printing

    Union was: {140, 180} {120, 180} {120, 140} {100, 140} {100, 200} {115, 200} {115, 250} {140, 250} 
    

    BONUS

    I'd probably write it more like:

    Live On Coliru

    #include <boost/polygon/point_traits.hpp>
    #include <boost/polygon/polygon.hpp>
    #include <boost/polygon/polygon_set_data.hpp>
    #include <boost/polygon/polygon_set_traits.hpp>
    #include <boost/polygon/polygon_traits.hpp>
    
    namespace gtl = boost::polygon;
    using namespace boost::polygon::operators;
    
    typedef gtl::polygon_90_data<int> Polygon;
    typedef gtl::polygon_traits<Polygon>::point_type Point;
    typedef gtl::polygon_90_set_data<int> PolygonSet;
    
    Polygon make_polygon(std::initializer_list<Point> init) {
        Polygon p;
        p.set(init.begin(), init.end());
        return p;
    }
    
    template <typename P>
    P get_union(P const& a, P const& b) {
        std::vector<P> v;
        PolygonSet(a+b).get(v);
        assert(v.size() == 1);
        return std::move(v.front());
    }
    
    int main() {
        Polygon u = get_union(
           make_polygon({ {100, 200}, {120, 200}, {120, 140}, {100, 140} }),
           make_polygon({ {115, 180}, {115, 250}, {140, 250}, {140, 180} }));
    
        for (auto& pt : u)
            std::cout << "{" << pt.x() << ", " << pt.y() << "} ";
    }
    

    Printing the same