Boost geometry union with auto-allocation

只愿长相守 提交于 2019-12-13 21:03:47

问题


#include <iostream> 
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/register/point.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>

using namespace boost::geometry;

class CustomPoint{
public:
    double X;
    double Y;
};

using cpPtr = boost::shared_ptr<CustomPoint>;

namespace boost { namespace geometry { namespace traits {
    BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_TRAITS(cpPtr, 2, double, cs::cartesian)

    template<> struct access<cpPtr, 0> {
        static inline double get(cpPtr const& p) { return p->X; }
        static inline void set(cpPtr& p, double const& value) { p->X = value; }
    };
    template<> struct access<cpPtr, 1> {
        static inline double get(cpPtr const& p) { return p->Y; }
        static inline void set(cpPtr& p, double const& value) { p->Y = value; }
    };
}}}

int main()
{
  std::vector<cpPtr> one,Two;
  //init polys
  std::vector< std::vector<cpPtr> > output;
  boost::geometry::union_(one,two,output)

}

Hello i tried a boost::shared_ptr as polygon. The problem is when i do union clipping the algorithm didn't allocate memory. Anyone knows a solution for this?


回答1:


First let me take the time to say I'm puzzled by the motivation for this "awkward" point type choice.

It seems to me that

  • if you have very few points, then the sharing would not appear to be essential
  • if you do then it would appear that the overhead of shared_ptr (2x pointer overhead and atomic reference count locking) would prevent scaling.

For the best of both worlds (points that can be in multiple collections at once) have you considered straight pointers, or perhaps even Boost Intrusive containers (which will not take ownership over contained elements)?

All question aside, here's one way to do it:


You can do a simplistic wrapper around a shared_ptr that allows you to use it in this way:

template<typename T>
    struct shared_instancing : boost::shared_ptr<T> {
        using boost::shared_ptr<T>::shared_ptr;

        shared_instancing(boost::shared_ptr<T> sp = boost::make_shared<T>()) 
            : boost::shared_ptr<T>(sp)
        { }
    };

As you can see, it will default construct to a new instance; See it Live On Coliru

#include <iostream> 
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/geometry/geometries/register/point.hpp>
#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>

using namespace boost::geometry;

struct CustomPoint{
    double X;
    double Y;
};

namespace {
    template<typename T>
        struct shared_instancing : boost::shared_ptr<T> {
            using boost::shared_ptr<T>::shared_ptr;

            shared_instancing(boost::shared_ptr<T> sp = boost::make_shared<T>()) 
                : boost::shared_ptr<T>(sp)
            { }
        };
}

using cpPtr = shared_instancing<CustomPoint>; // boost::shared_ptr<CustomPoint>;

namespace boost { namespace geometry { namespace traits {
    BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_TRAITS(cpPtr, 2, double, cs::cartesian)

    template<> struct access<cpPtr, 0> {
        static inline double get(cpPtr const& p) { return p->X; }
        static inline void set(cpPtr& p, double const& value) { p->X = value; }
    };
    template<> struct access<cpPtr, 1> {
        static inline double get(cpPtr const& p) { return p->Y; }
        static inline void set(cpPtr& p, double const& value) { p->Y = value; }
    };
}}}

int main()
{
    typedef boost::geometry::model::polygon<cpPtr > polygon;

    polygon green, blue;

    boost::geometry::read_wkt(
        "POLYGON((2 1.3,2.4 1.7,2.8 1.8,3.4 1.2,3.7 1.6,3.4 2,4.1 3,5.3 2.6,5.4 1.2,4.9 0.8,2.9 0.7,2 1.3)"
            "(4.0 2.0, 4.2 1.4, 4.8 1.9, 4.4 2.2, 4.0 2.0))", green);

    boost::geometry::read_wkt(
        "POLYGON((4.0 -0.5 , 3.5 1.0 , 2.0 1.5 , 3.5 2.0 , 4.0 3.5 , 4.5 2.0 , 6.0 1.5 , 4.5 1.0 , 4.0 -0.5))", blue);

    std::vector<polygon> output;
    boost::geometry::union_(green, blue, output);

    int i = 0;
    std::cout << "green || blue:" << std::endl;
    for(polygon const& p: output)
    {
        std::cout << i++ << ": " << boost::geometry::area(p) << std::endl;
    }
}


来源:https://stackoverflow.com/questions/26100112/boost-geometry-union-with-auto-allocation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!