Search code examples
c++algorithmboostboost-geometry

How can I check if a ring is contained in another ring using Boost.Geometry?


I am trying to determine whether a ring is contained by another ring using the Boost.Geometry library.

I wrote the following code:

#include <iostream>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/geometries.hpp>

using namespace boost::geometry;

int main (int argc, const char * argv[])
{
    typedef model::d2::point_xy<double> P;
    model::ring<P> ring1, ring2;

    read_wkt("polygon((0 0,0 3,3 3,3 0,0 0))", ring1);
    read_wkt("polygon((1 1,1 2,2 2,2 1,1 1))", ring2);

    bool b = within(ring1, ring2);
    std::cout << "Within: " << (b ? "YES" : "NO") << std::endl;

    return 0;
}

But it does not compile (with Boost 1.48.0), because it fails a static assertion of within:

NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE

It seems that within only supports checking whether a point is within another geometry (according to the documentation).

I was thinking about treating the rings as linestrings, then check whether they intersect, and if not - check if the first point of the ring is within the other ring; but I don't know if it's possible to avoid copying each ring to a linestring.

Is there any way to achieve the functionality of within for two rings (with reasonable performance)?


Solution

  • I ended up implementing the idea I suggested in the question:

    using namespace boost::geometry;
    
    template <typename Point>
    bool within(const model::ring<Point>& ring1, const model::ring<Point>& ring2)
    {
        return within(ring1.front(), ring2) &&
               disjoint(model::linestring<Point>(ring1.begin(), ring1.end()),
                        model::linestring<Point>(ring2.begin(), ring2.end()));
    }
    

    Seems to good enough for me, but I'd still be glad to get some suggestions.