I've created an application with boost geometry which defines an own polygon type with some additional data called
struct taggedPolygon_t : bg::model::polygon<point_t>
{
taggedPolygon_t() {}
std::string mask_;
};
Which carries some additional information.
What I want to achieve is the boost::geometry::union_ also handles this additional data. In my sample case it would be sufficient if member "mask" is unified like this or similar
resultPoly.mask = poly1.mask + poly2.mask;
I tried to create a sample application - but it's at the limits of Coliru.
I think everyone should get the idea?
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/geometries.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/algorithms/area.hpp>
#include <iostream>
namespace bg = boost::geometry;
using point_t = bg::model::d2::point_xy<double>;
struct taggedPolygon_t : bg::model::polygon<point_t>
{
taggedPolygon_t() {}
std::string mask_;
};
namespace boost::geometry::traits
{
template<> struct tag<taggedPolygon_t> { typedef polygon_tag type; };
template<> struct ring_const_type<taggedPolygon_t> { typedef const bg::model::polygon<point_t>::ring_type& type; };
template<> struct ring_mutable_type<taggedPolygon_t> { typedef bg::model::polygon<point_t>::ring_type& type; };
template<> struct interior_const_type<taggedPolygon_t> { typedef const bg::model::polygon<point_t>::inner_container_type& type; };
template<> struct interior_mutable_type<taggedPolygon_t> { typedef bg::model::polygon<point_t>::inner_container_type& type; };
template<> struct exterior_ring<taggedPolygon_t>
{
static bg::model::polygon<point_t>::ring_type& get(bg::model::polygon<point_t>& p) {return p.outer(); }
static bg::model::polygon<point_t>::ring_type const& get(bg::model::polygon<point_t> const& p) {return p.outer(); }
};
template<> struct interior_rings<taggedPolygon_t>
{
static bg::model::polygon<point_t>::inner_container_type& get(bg::model::polygon<point_t>& p) {return p.inners(); }
static bg::model::polygon<point_t>::inner_container_type const& get(bg::model::polygon<point_t> const& p) {return p.inners(); }
};
} // namespace boost::geometry::traits
using multiTaggedPolygon_t = bg::model::multi_polygon<taggedPolygon_t>;
int main() {
multiTaggedPolygon_t polygons;
bg::read_wkt("MULTIPOLYGON (((40 40, 20 45, 45 30, 40 40)), "
"((20 35, 10 30, 10 10, 30 5, 45 20, 20 35),"
"(30 20, 20 15, 20 25, 30 20)))", polygons);
std::string reason;
if (!bg::is_valid(polygons, reason)) {
std::cout << "Correcting data: " << reason << "\n";
bg::correct(polygons);
}
multiTaggedPolygon_t separated(std::move(polygons));
multiTaggedPolygon_t newPolygons;
for (auto& poly : separated)
{
// Unify polygons
bg::union_(polygons, poly, newPolygons);
std::swap(polygons, newPolygons);
newPolygons.clear();
}
for (auto& p : polygons)
std::cout << p.mask_ << std::endl;
}
http://coliru.stacked-crooked.com/a/ff15c25e4d672ebd
I thought that the strategies() parameter of the union_ function would be the way to go but I'm stuck as there seems to be no specific documentation for this case?
This is frequently requested, sad thing is due to the concepts there is no way to piggy-back meta data in geometry entities (specifically, points).
Points are default constructible, and are assigned coordinates using the accessor functions.
This is important for the generic case: if the output geometry has an entirely different types. Yes, specially for union_
you might expect some input points to be copy-constructed, but alas.
I've previosly explained this in some more detail here: