TestUser
TestUser

Reputation: 967

Boost polygon union result is differing between windows and linux

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";

}

Upvotes: 1

Views: 240

Answers (2)

TestUser
TestUser

Reputation: 967

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.

Upvotes: 2

sehe
sehe

Reputation: 392911

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";
}

Upvotes: 0

Related Questions