1

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

}
Test
  • 564
  • 3
  • 12

2 Answers2

1

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.

Test
  • 564
  • 3
  • 12
0

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";
}
sehe
  • 374,641
  • 47
  • 450
  • 633
  • Thanks. SO what you mean that you were unable to see the answer which i am seeing i.e o/p showing two polygons separated by a line in the middle? WHat would be the easiest way to determine the boost version i am using in CentOS? Is it possible to see via some header etc? – Test Nov 13 '21 at 17:17
  • Of course. I'm not going to give you exact advice, since we lack the information on how you configured things, but `boost/version.hpp` would be the thing to look for (you can also just include and output the number defined in it) – sehe Nov 13 '21 at 17:22
  • boost version seems like 1.68.0 . I have absolutely no idea why i am getting this weird output when my code runs as part of a larger project. WIth this individual test program it works OK but as part of the bigger project it gives the output which i posted in original question (seems like union is just collecting all individual inputs as such). Beats me – Test Nov 13 '21 at 18:46
  • Maybe you can reduce the surrounding code until the problem disappears, isolating the cause – sehe Nov 13 '21 at 19:09
  • the debugging shows my faulty code is just adding the individual polygons as such to the union polygon in CentOS. The same code works perfect in Windows. I am really confused as why on CentOS its just adding individual polygons in the union instead of doing like windows. – Test Nov 14 '21 at 02:34
  • Again, try to eliminate sources of the bug. You will find it. – sehe Nov 14 '21 at 02:37
  • i think i found the culprit. The big project was defining a flag called BOOST_GEOMETRY_NO_ROBUSTNESS. I don't know what this flag is. Do you have any idea? Using this flag in linux made the output become different for my test program. – Test Nov 16 '21 at 05:09
  • I didn't know that flag and Google tells me it turns off integer rescaling. Barend Gehrels has some nice Blog posts about the issue of floating point precision relating to computational geometry (e.g. https://barendgehrels.blogspot.com/2011/01/precision-cause-of-spikes.html) it contains some work-around suggestions in case that's the cause. – sehe Nov 16 '21 at 11:30