11

So I want to join all interrelated poligons in a multi_polygon. How to do such thing?

We have such image (of one green multi_polygon) which we want to optimize (we can see yellow doted lines - result of simplification that apparently was performed on each poligon of multi_polygon not on multi_polygon in general):

enter image description here

And here is compilable code to generate such image:

#include <iostream>
#include <fstream>
#include <boost/assign.hpp>

#include <boost/algorithm/string.hpp>
#include <boost/geometry/geometry.hpp>
#include <boost/geometry/geometries/geometries.hpp>
#include <boost/geometry/multi/geometries/multi_polygon.hpp>

#include <boost/geometry/extensions/io/svg/svg_mapper.hpp>

template <typename Geometry1, typename Geometry2>
void create_svg(std::string const& filename, Geometry1 const& a, Geometry2 const& b)
{
    typedef typename boost::geometry::point_type<Geometry1>::type point_type;
    std::ofstream svg(filename.c_str());

    boost::geometry::svg_mapper<point_type> mapper(svg, 400, 400);
    mapper.add(a);
    mapper.add(b);

    mapper.map(a, "fill-opacity:0.5;fill:rgb(153,204,0);stroke:rgb(153,204,0);stroke-width:2");
    mapper.map(b, "opacity:0.8;fill:none;stroke:rgb(255,128,0);stroke-width:4;stroke-dasharray:1,7;stroke-linecap:round");
}


boost::geometry::model::polygon<boost::geometry::model::d2::point_xy<double> > make_point(int x, int y)
{
    boost::geometry::model::polygon<boost::geometry::model::d2::point_xy<double> > return_item;
    boost::geometry::model::d2::point_xy<double> p1(x, y);
    boost::geometry::model::d2::point_xy<double> p2(x-1, y);
    boost::geometry::model::d2::point_xy<double> p3(x-1, y-1);
    boost::geometry::model::d2::point_xy<double> p4(x, y-1);

    boost::geometry::append(  return_item, p1);
    boost::geometry::append(  return_item, p2);
    boost::geometry::append(  return_item, p3);
    boost::geometry::append(  return_item, p4);

    return return_item;

}

int main()
{
    // create a container for joined points structure
    boost::geometry::model::multi_polygon< boost::geometry::model::polygon<boost::geometry::model::d2::point_xy<double> > > output, simpl;

    // join points one by one (because one day we would have many=))
    output.push_back(make_point(1,1));
    boost::geometry::correct(output);

    output.push_back(make_point(2,1));
    boost::geometry::correct(output);

    output.push_back(make_point(3,1));
    boost::geometry::correct(output);

    output.push_back(make_point(4,1));
    boost::geometry::correct(output);

    output.push_back(make_point(5,1));
    boost::geometry::correct(output);

    output.push_back(make_point(2,2));
    boost::geometry::correct(output);

    output.push_back(make_point(3,2));
    boost::geometry::correct(output);

    output.push_back(make_point(5,2));
    boost::geometry::correct(output);

    output.push_back(make_point(5,5));
    boost::geometry::correct(output);


    // simplify joined structure
    boost::geometry::simplify(output, simpl, 0.5);

    // create an svg image
    create_svg("make_envelope.svg",  output, simpl );
}

requires at least boost 1.47.0 and 3 files from boost/geometry/extensions/io/svg/

what I need is simple: how to group interrelated poligons? In this case we shall get 2 poligons in our multy_poligon like shown here - red and green:

enter image description here

Update:

So I found this info on dissolve and created sample code that uses rings for cels creation:

#include <iostream>
#include <fstream>
#include <boost/assign.hpp>

//Boost
#include <boost/algorithm/string.hpp>
#include <boost/geometry/geometry.hpp>
#include <boost/geometry/geometries/geometries.hpp>
#include <boost/geometry/multi/geometries/multi_polygon.hpp>
#include <boost/geometry/geometries/adapted/boost_tuple.hpp>

BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian)

#include <boost/foreach.hpp>

//Boost Geometry extensions (from trunk) 
#include <boost/geometry/extensions/io/svg/svg_mapper.hpp>

template <typename Geometry1, typename Geometry2>
void create_svg(std::string const& filename, Geometry1 const& a, Geometry2 const& b)
{
    typedef typename boost::geometry::point_type<Geometry1>::type point_type;
    std::ofstream svg(filename.c_str());

    boost::geometry::svg_mapper<point_type> mapper(svg, 400, 400);
    mapper.add(a);
    mapper.add(b);

    mapper.map(a, "fill-rule:nonzero;fill-opacity:0.5;fill:rgb(153,204,0);stroke:rgb(153,204,0);stroke-width:2;");
    mapper.map(b, "opacity:0.8;fill:none;stroke:rgb(255,128,0);stroke-width:4;stroke-dasharray:1,7;stroke-linecap:round");
}

void make_point(int x, int y, boost::geometry::model::ring<boost::geometry::model::d2::point_xy<double> > & ring)
{
    using namespace boost::assign;

    ring += 
        boost::geometry::model::d2::point_xy<double>(x-1, y-1),
        boost::geometry::model::d2::point_xy<double>(x, y-1),
        boost::geometry::model::d2::point_xy<double>(x, y),
        boost::geometry::model::d2::point_xy<double>(x-1, y),
        boost::geometry::model::d2::point_xy<double>(x-1, y-1);

}

int main()
{
    using namespace boost::assign;
    boost::geometry::model::ring<boost::geometry::model::d2::point_xy<double> > ring0, ring1,ring;

    boost::geometry::model::multi_polygon< boost::geometry::model::polygon<boost::geometry::model::d2::point_xy<double> > > outputw;

    make_point(1, 1, ring) ;
    make_point(2, 1, ring) ;
    make_point(3, 1, ring) ;
    make_point(4, 1, ring) ;
    make_point(5, 1, ring) ;
    make_point(2, 2, ring) ;
    make_point(3, 2, ring) ;
    make_point(5, 2, ring) ;

    boost::geometry::model::ring<boost::geometry::model::d2::point_xy<double> > output;
    boost::geometry::simplify(ring, output, 1);

    // create an svg image
    create_svg("make_envelope.svg",  ring, output );
}

It returns such image of ring:

enter image description here

If we could use dissolve to turn it into poligon that would really solve some of my problems. But looks like currently we can not due to this compiler errors problem described here

Community
  • 1
  • 1
Rella
  • 59,216
  • 102
  • 341
  • 614
  • I think you might be looking for Connectivity Extraction: http://www.boost.org/doc/libs/1_47_0/libs/polygon/doc/gtl_connectivity_extraction.htm – Nathan Monteleone Nov 08 '11 at 15:22

2 Answers2

9

What about using Qt. If you use a QPolygonF you can call unite which does exactly what you need. After unison you can extract the points and put them back into your boost container.

If qt is not an option take a look at the algorithms proposed here http://www.wykobi.com

Martin
  • 4,346
  • 2
  • 25
  • 54
0

You can use this function from boost library:

void union_(Geometry1 const & geometry1, Geometry2 const & geometry2, Collection & output_collection)

It takes two geometries and unites them if they have intersections or puts them into one collection (vector, deque, etc.) if not.