skip to Main Content

I am trying to get a union of all the individual polygons via boost geometry. But oddly the results seem to vary between windows and centOS.

The result is coming out right one (the one i expect) in windows BUT in linux its odd. In linux it shows result as two split polygons.

In Windows i get

MULTIPOLYGON(((0 -0,0 2996,1490 2996,2980 2996,2980 -0,0 -0)))

But in centOS same set of inputs, give result as

MULTIPOLYGON(((1490 2996,2980 2996,2980 -0,1490 -0,1490 2996)),((0 2996,1490 2996,1490 -0,0 -0,0 2996)))

Its baffling for me as the code trying to compute polygons union is same. I don’t understand why the linux output is coming out with a split line in between polygons. That’s not how a union output should look like.

Can anyone point out what is that i am doing wrong in below code? Or any other pointers which i could try to see whats going wrong.

#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/geometry/geometries/multi_polygon.hpp>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/geometries.hpp>
#include <vector>
#include <boost/geometry.hpp>
#include <boost/geometry/io/wkt/wkt.hpp>


namespace boost {
    namespace geometry {

        typedef model::d2::point_xy<double> Point;
        typedef model::polygon<Point> Polygon;
        typedef model::segment<Point> Line;

    };
};

int main()
{


        using multi_polygon = boost::geometry::model::multi_polygon<boost::geometry::Polygon>;


        boost::geometry::Polygon one, two,green;



        boost::geometry::read_wkt("POLYGON((0 2996, 1490 2996, 1490 -0, 0 -0, 0 2996))", one);

        boost::geometry::read_wkt("POLYGON((1490 2996, 2980 2996, 2980 -0, 1490 -0, 1490 2996))", two);

        multi_polygon polyUnion;
        std::vector<boost::geometry::Polygon> vectorOfPolygons;

        vectorOfPolygons.emplace_back(one);
        vectorOfPolygons.emplace_back(two);


        // Create the union of all the polygons of the datasets
        for (const boost::geometry::Polygon& p : vectorOfPolygons) {
            multi_polygon tmp;
            boost::geometry::union_(polyUnion, p, tmp);
            polyUnion = tmp;
            boost::geometry::clear(tmp);
        }

        std::string str;
        bool valid = boost::geometry::is_valid(polyUnion, str);

        if (!valid)
        {
            boost::geometry::correct(polyUnion);
        }

        std::cout << "Result of union" << boost::geometry::wkt(polyUnion) << "n";

}

2

Answers


  1. Chosen as BEST ANSWER

    The flag BOOST_GEOMETRY_NO_ROBUSTNESS made the boost API behave differently for same set of inputs in linux. Turning OFF this flag made the output to become same in windows and linux.


  2. You’re likely not using the same version of boost.

    Compare:

    That’s the earliest version of Boost that even has the multi_polygon header.

    I tried some more combinations (e.g. with -ffast-math) just to see whether I could get your exact output from the question, but I guess we need more information to reproduce that (versions and flags).

    Listing

    #include <boost/geometry.hpp>
    #include <boost/geometry/geometries/geometries.hpp>
    #include <boost/geometry/geometries/multi_polygon.hpp>
    #include <boost/geometry/geometries/point_xy.hpp>
    #include <boost/geometry/geometries/polygon.hpp>
    #include <boost/geometry/io/wkt/wkt.hpp>
    #include <iostream>
    #include <vector>
    namespace bg = boost::geometry;
    namespace bgm = bg::model;
    
    using Point     = bgm::d2::point_xy<double>;
    using Polygon   = bgm::polygon<Point>;
    using MultiPoly = bg::model::multi_polygon<Polygon>;
    
    int main()
    {
        auto check = [](auto name, auto& g) {
            if (std::string reason; !bg::is_valid(g, reason)) {
                std::cout << name << ": " << reason << "n";
                bg::correct(g);
            }
        };
    
        Polygon one, two;
        bg::read_wkt("POLYGON((0 2996, 1490 2996, 1490 -0, 0 -0, 0 2996))", one);
        bg::read_wkt("POLYGON((1490 2996, 2980 2996, 2980 -0, 1490 -0, 1490 2996))", two);
        check("one", one);
        check("two", two);
    
        MultiPoly polyUnion;
    
        // Create the union of all the polygons of the datasets
        for (auto& p : {one, two}) {
            MultiPoly tmp;
            bg::union_(polyUnion, p, tmp);
            polyUnion = tmp;
        }
    
        check("polyUnion", polyUnion);
    
        std::cout << "polyUnion: " << bg::wkt(polyUnion) << "n";
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search