2

I'm trying to intersect two polygons by using the Boost Polygon library. I'm started from the example of a custom_polygon proposed from the boost website:

http://www.boost.org/doc/libs/1_59_0/libs/polygon/doc/gtl_custom_polygon.htm

In the test_polygon function I fill two polygons. My question is if it's possible to call the intersection function with poly1 and poly2. If I compile I have a very long list of errors.

#include <boost/polygon/polygon.hpp>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>

#include <list>


// My Point class
class MyPoint {
public:
    double x, y;
};

// MyPolygon as a list of MyPoint
typedef std::list<MyPoint> MyPolygon;



template <>
struct boost::polygon::geometry_concept<MyPoint> {
    typedef point_concept type;
};

template <>
struct boost::polygon::point_traits<MyPoint> {

    typedef double coordinate_type;

    static inline coordinate_type get(const MyPoint& point, boost::polygon::orientation_2d orient) {
        if (orient == boost::polygon::HORIZONTAL)
            return point.x;
        return point.y;
    }
};


template <>
struct boost::polygon::point_mutable_traits<MyPoint> {

    typedef double coordinate_type;

    static inline void set(MyPoint& point, boost::polygon::orientation_2d orient, double value) {
        if (orient == boost::polygon::HORIZONTAL)
            point.x = value;
        else
            point.y = value;
    }

    static inline MyPoint construct(double x_value, double y_value) {
        MyPoint retval;
        retval.x = x_value;
        retval.y = y_value;
        return retval;
    }
};



template <>
struct  boost::polygon::geometry_concept<MyPolygon>{
    typedef  boost::polygon::polygon_concept type;
};


template <>
struct  boost::polygon::polygon_traits<MyPolygon> {

    typedef double coordinate_type;

    typedef MyPolygon::const_iterator iterator_type;

    typedef MyPoint point_type;

    static inline iterator_type begin_points(const MyPolygon& t) {
        return t.begin();
    }
    static inline iterator_type end_points(const MyPolygon& t) {
        return t.end();
    }

    // Get the number of sides of the polygon
    static inline std::size_t size(const MyPolygon& t) {
        return t.size();
    }

    // Get the winding direction of the polygon
    static inline winding_direction winding(const MyPolygon& t) {
        return unknown_winding;
    }
};


template <>
struct  boost::polygon::polygon_mutable_traits<MyPolygon> {

    //expects stl style iterators
    template < typename iT >
    static inline MyPolygon& set_points(MyPolygon& t, iT input_begin, iT input_end) {
        t.clear();
        t.insert(t.end(), input_begin, input_end);
        return t;
    }
};




template < typename Polygon, typename Point >
void test_polygon() {

    Polygon poly1, poly2;

    // Define a vector container
    std::vector< boost::polygon::polygon_traits< Polygon >::point_type  > vpoints;

    vpoints.push_back(boost::polygon::construct<Point>(0.0, 0.0));
    vpoints.push_back(boost::polygon::construct<Point>(0.0, 1.0));
    vpoints.push_back(boost::polygon::construct<Point>(1.0, 1.0));
    vpoints.push_back(boost::polygon::construct<Point>(1.0, 0.0));
    vpoints.push_back(boost::polygon::construct<Point>(0.05, 0.0));
    boost::polygon::set_points(poly1, vpoints.begin(), vpoints.end());
    vpoints.clear();

    vpoints.push_back(boost::polygon::construct<Point>(0.5, -0.5));
    vpoints.push_back(boost::polygon::construct<Point>(0.5, 0.5));
    vpoints.push_back(boost::polygon::construct<Point>(1.5, 0.5));
    vpoints.push_back(boost::polygon::construct<Point>(1.5, -0.5));
    vpoints.push_back(boost::polygon::construct<Point>(0.5, -0.5));
    boost::polygon::set_points(poly2, vpoints.begin(), vpoints.end());

    std::deque<Polygon> output;
    boost::geometry::intersection(poly1, poly2, output);  // ERROR!!!

}




int main() {
    test_polygon< MyPolygon, MyPoint >();
    system("pause");
    return 0;
}
genpfault
  • 51,148
  • 11
  • 85
  • 139
  • The traits you're using are for boost polygon. That's another library than boost geometry. – sehe Sep 18 '15 at 13:01

1 Answers1

5

You seem to be confusing two boost libraries.

Here's a quick adaptation using just Boost Geometry:

Live On Coliru

#include <boost/geometry.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/geometries/register/point.hpp>
#include <boost/geometry/geometries/register/linestring.hpp>

namespace bg = boost::geometry;

struct MyPoint {
    double x, y;
};

typedef std::vector<MyPoint> MyPolygon;

BOOST_GEOMETRY_REGISTER_POINT_2D(MyPoint, double, bg::cs::cartesian, x, y)
BOOST_GEOMETRY_REGISTER_LINESTRING(MyPolygon)

template < typename Polygon, typename Point >
std::deque<Polygon> test_polygon() {

    Polygon poly1 { {0.0,  0.0}, {0.0, 1.0}, {1.0, 1.0}, {1.0,  0.0}, {0.05,  0.0}, };
    Polygon poly2 { {0.5, -0.5}, {0.5, 0.5}, {1.5, 0.5}, {1.5, -0.5},  {0.5, -0.5}, };

    std::deque<Polygon> output;
    boost::geometry::intersection(poly1, poly2, output); 

    return output;
}

int main() {
    for (auto& p : test_polygon< MyPolygon, MyPoint >())
        std::cout << "Intersection: " << bg::wkt(p) << "\n";
}

Prints:

Intersection: LINESTRING(1 0.5,1 0.5)
Intersection: LINESTRING(0.5 0,0.5 0)

Notes

I replaced list with vector because the *REGISTER_LINESTRING macro requires random access iterators. You can go the 'complicated' route if you really can help it being std::list, but that will likely make the algorithms inefficient:

sehe
  • 374,641
  • 47
  • 450
  • 633
  • Thank you very very very much!!! now I understand my mistakes and the code do what I want. For me no problem to chang from list to vector. – Gabriele Cuccolini Sep 18 '15 at 13:40
  • Hi, I check the algorithm and the intersection points between the polygonals are ok. I have another question, Is it possible also to obtain the intersection polygon with this kind of structure? – Gabriele Cuccolini Sep 22 '15 at 11:42
  • That's what you get. Except, it's a multi-polygon, because the generic intersection of two shapes could be several (disjunct) polygons – sehe Sep 22 '15 at 11:43
  • 2
    If I use BOOST_GEOMETRY_REGISTER_RING( std::vector ) instead of BOOST_GEOMETRY_REGISTER_LINESTRING(MyPolygon) I obtain the points of the intersection polygon – Gabriele Cuccolini Sep 22 '15 at 13:50
  • Oh. I might have misunderstood something. Good that you found it yourself! – sehe Sep 22 '15 at 14:04
  • Anyone knows if it is possible to call a boost::geometry::intersection from multiple threads? I've a multithread application that call boost geometry functions like polygon intersections or buffer from different threads. – Gabriele Cuccolini Nov 20 '15 at 11:38
  • Yes that's possible. Even from the same geometries iff they're constant. Just make sure there's no shared mutable state as always in threading – sehe Nov 20 '15 at 11:40
  • In this example, how is it possible to 'pushback()' points to the polygon? – Bruce Feb 28 '18 at 14:12
  • 1
    @Bruce nothing to do with the example, and "it depends" on the polygon model. However, the library has some generic accessors for it: http://www.boost.org/doc/libs/1_66_0/libs/geometry/doc/html/geometry/reference/algorithms/append.html – sehe Feb 28 '18 at 14:16