Boost :: simplifying geometry union - how does it work?

Boost has a large library for geometry. It also allows you to draw SVG images. I want to use it in some kind of project, but for me it is really strange (see image below).

So, we have 3 pixel points represented as square polygons in 2d-space

1 1 0 1 

enter image description here pic 1

we want to get a union from them and simplify it so that when scaling we get a triangle similar to

 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 0 0 1 1 1 1 0 0 0 1 1 1 

enter image description here pic 2

but we get the following:

enter image description here

where the yellow line is the union and the green is the simplification.

Source:

 #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/algorithms/envelope.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"); } int main() { // create points (each point == square poligon) boost::geometry::model::polygon<boost::geometry::model::d2::point_xy<double> > one, two, three; boost::geometry::read_wkt( "POLYGON((1 1, 1 0, 0 0, 0 1))", one); boost::geometry::read_wkt( "POLYGON((2 2, 2 1, 1 1, 1 2))", two); boost::geometry::read_wkt( "POLYGON((1 1, 1 2, 0 2, 0 1))", three); // 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=)) boost::geometry::union_(one, two, output); boost::geometry::union_( output , three, output); // simplify joined structure boost::geometry::simplify(output, simpl, 0.5); // create an svg image create_svg("make_envelope.svg", simpl, output ); } 

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

So, how to make this simplified, since I want the value to get a form like pic 2 ?

Update

New code created, it works correctly, fully tested:

 #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> #include <boost/foreach.hpp> //and this is why we use Boost Geometry from Boost trunk #include <boost/geometry/extensions/io/svg/svg_mapper.hpp> BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian) 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::polygon<boost::geometry::model::d2::point_xy<double> > & ring) { using namespace boost::assign; boost::geometry::append( ring, boost::geometry::model::d2::point_xy<double>(x-1, y-1)); boost::geometry::append( ring, boost::geometry::model::d2::point_xy<double>(x, y-1)); boost::geometry::append( ring, boost::geometry::model::d2::point_xy<double>(x, y)); boost::geometry::append( ring, boost::geometry::model::d2::point_xy<double>(x-1, y)); boost::geometry::append( ring, boost::geometry::model::d2::point_xy<double>(x-1, y-1)); boost::geometry::correct(ring); } void create_point(int x, int y, boost::geometry::model::multi_polygon< boost::geometry::model::polygon<boost::geometry::model::d2::point_xy<double> > > & mp) { boost::geometry::model::multi_polygon< boost::geometry::model::polygon<boost::geometry::model::d2::point_xy<double> > > temp; boost::geometry::model::polygon<boost::geometry::model::d2::point_xy<double> > ring; make_point(x, y, ring); boost::geometry::union_(mp, ring, temp); boost::geometry::correct(temp); mp=temp; } int main() { using namespace boost::assign; typedef boost::geometry::model::polygon < boost::geometry::model::d2::point_xy<double> > polygon; typedef boost::geometry::model::multi_polygon<polygon> mp; polygon ring; mp pol, simpl; polygon exring; create_point(1,1, pol); create_point(2, 1, pol); create_point(3, 1, pol); create_point(4,1, pol); create_point(5, 1, pol); create_point(1,2, pol); create_point(2, 2, pol); create_point(3, 2, pol); create_point(4,2, pol); create_point(5, 2, pol); create_point(2, 3, pol); create_point(3, 3, pol); create_point(5, 3, pol); create_point(3, 4, pol); create_point(5, 3, pol); create_point(5, 5, pol); //boost::geometry::dissolve(ring, pol); // Baad boost::geometry::simplify(pol, simpl, 0.5); // Good create_svg("make_envelope.svg",pol, simpl ); } 

And this code creates an image like this:

enter image description here

And for 3 points it returns @J images . Calleja :

enter image description here

+8
c ++ boost boost-geometry
source share
1 answer

I think there are several problems with the code:

  • Polygons that you define:

eleven
10

I.e:

 three two one - 

Thus, the expected result is different from pic2.

  • Landfills must be closed and turned clockwise.

You are missing the closing point, and the third polygon is not clockwise. Take a look at the correct method. In this example, you must call it for each polygon you define.

  • You cannot use the same argument for input and output when using _union.

You should use a temporary variable:

  boost::geometry::union_(one, two, outputTmp); boost::geometry::union_( outputTmp, three, output); 
  • The expected result may not be the result of an algorithm.

After executing the corrected code, the result:

simplify result

This may be a legitimate simplification of your landfill. See the Ramer-Douglas-Puker algorithm .

After making these changes, below is the result of main ()

 int main() { // create points (each point == square poligon) boost::geometry::model::polygon<boost::geometry::model::d2::point_xy<double> > one, two, three; boost::geometry::read_wkt( "POLYGON((1 1, 1 0, 0 0, 0 1))", one); boost::geometry::read_wkt( "POLYGON((2 2, 2 1, 1 1, 1 2))", two); boost::geometry::read_wkt( "POLYGON((1 1, 1 2, 0 2, 0 1))", three); boost::geometry::correct(one); boost::geometry::correct(two); boost::geometry::correct(three); // create a container for joined points structure boost::geometry::model::multi_polygon< boost::geometry::model::polygon<boost::geometry::model::d2::point_xy<double> > > outputTmp, output, simpl; // join points one by one (because one day we would have many=)) boost::geometry::union_(one, two, outputTmp); boost::geometry::union_( outputTmp, three, output); // simplify joined structure boost::geometry::simplify(output, simpl, 0.5); // create an svg image create_svg("make_envelope.svg", simpl, output ); } 
+4
source share

All Articles