C ++ Boost Loop through model dimensions :: point

I was wondering if there is a way to cut through the dimensions of the alarm point model. I am trying to create a function to do a calculation at two configurable points with a specific number of dimensions. In other words, the number of measurements for each point will correspond, but they will not be a constant value. I want to do the same operations on each dimension, so I need to do a loop to achieve this.

An example of what I want, I want to do:

for(std::size_t dim = 0; dim < D; dim++){
    CoordinateType d = get<dim>();

    //do stuff to d

    set<dim>(d);

}

      

I know it won't work because it is d

not a compile-time constant.

Thank!

+3


source to share


2 answers


As an alternative approach, I thought that you should adapt the exact Boost Geometry model as a Fusion sequence.

Live On Coliru

#include <iostream>

namespace bg  = boost::geometry;
namespace fus = boost::fusion;

int main() {
    bg::model::point<double, 7, bg::cs::cartesian> p1;
    // set some nice values
    p1.set<0>(7);  p1.set<1>(14); p1.set<2>(21); p1.set<3>(28);
    p1.set<4>(35); p1.set<5>(42); p1.set<6>(49);

    fus::for_each(fus::as_vector(p1), [](double x) { std::cout << x << ' '; });
}

      

Printing

7 14 21 28 35 42 49 

      



It's pretty versatile (and will give you a lot more algorithms than just that for_each

). In the sample, I didn't go all the way for you to say for_each(p1, f)

instead for_each(as_vector(p1), f)

, but you know ... the notorious exercise for the reader.

This is where the "glue" extension code is involved a bit. I just followed the documentation here

See the full list here:

Live On Coliru

#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/geometries/point.hpp>

#include <boost/fusion/include/for_each.hpp>
#include <boost/fusion/include/as_vector.hpp>

namespace bg_to_fusion {
    using namespace boost;

    struct bg_point_tag;
    struct example_struct_iterator_tag;

    template<typename Point, int Pos>
    struct point_iterator
        : fusion::iterator_base<point_iterator<Point, Pos> >
    {
        BOOST_STATIC_ASSERT(Pos >=0 && Pos <geometry::traits::dimension<typename remove_cv<Point>::type>::value);

        typedef Point point_type;
        typedef mpl::int_<Pos> index;
        //typedef fusion::random_access_traversal_tag category;
        typedef fusion::forward_traversal_tag category;

        point_iterator(Point& p) : point_(p) {}
        Point& point_;
    };
}

namespace boost { namespace fusion {

    // tag dispatch
    namespace traits {

        template <typename T, size_t dims, typename cs>
        struct tag_of<geometry::model::point<T, dims, cs> > {
            typedef bg_to_fusion::bg_point_tag type;
        };

        template <typename Point, int Pos>
        struct tag_of<bg_to_fusion::point_iterator<Point, Pos> > {
            typedef bg_to_fusion::example_struct_iterator_tag type;
        };

    }

    namespace extension {

        //////////////////////////////////////////////////////
        // Point extension implementations
        template<>
        struct is_sequence_impl<bg_to_fusion::bg_point_tag>
        {
            template<typename T>
                struct apply : mpl::true_ {};
        };

        template <>
        struct size_impl<bg_to_fusion::bg_point_tag> {
            template <typename Point>
            struct apply : mpl::integral_c<size_t, geometry::traits::dimension<typename remove_cv<Point>::type>::value> { };
        };

        // begin
        template<>
        struct begin_impl<bg_to_fusion::bg_point_tag>
        {
            template<typename Point> 
            struct apply 
            {
                typedef typename bg_to_fusion::point_iterator<Point, 0> type;

                static type
                call(Point& p) 
                {
                    return type(p);
                }
            };
        };

        // end
        template<>
        struct end_impl<bg_to_fusion::bg_point_tag>
        {
            template<typename Point> struct apply {
                typedef typename bg_to_fusion::point_iterator<Point, geometry::traits::dimension<Point>::value> type;

                static type call(Point& p) {
                    return type(p);
                }
            };
        };

        ////////////////////////
        // Iterator extension implementations

        // value_of
        template <>
        struct value_of_impl<bg_to_fusion::example_struct_iterator_tag> {
            template<typename Iterator> struct apply;

            template<typename Point, int Pos> 
            struct apply<bg_to_fusion::point_iterator<Point, Pos> > {
                typedef typename geometry::traits::coordinate_type<typename remove_cv<Point>::type>::type type;
            };
        };

        // deref
        template<>
        struct deref_impl<bg_to_fusion::example_struct_iterator_tag>
        {
            template<typename Iterator>
            struct apply;

            template<typename Point, int Pos>
            struct apply<bg_to_fusion::point_iterator<Point, Pos> >
            {
                typedef typename geometry::traits::coordinate_type<typename remove_cv<Point>::type>::type coordinate_type;

                //typedef typename mpl::if_<is_const<Point>, coordinate_type const&, coordinate_type&>::type type;
                typedef coordinate_type type;

                static type
                call(bg_to_fusion::point_iterator<Point, Pos> const& it) {
                    return it.point_.template get<Pos>();
                }
            };
        };

        // next
        template<>
            struct next_impl<bg_to_fusion::example_struct_iterator_tag> {
                template<typename Iterator> struct apply
                {
                    typedef typename Iterator::point_type point_type;
                    typedef typename Iterator::index    index;
                    typedef typename bg_to_fusion::point_iterator<point_type, index::value + 1> type;

                    static type
                        call(Iterator const& i) {
                            return type(i.point_);
                        }
                };
            };
    }

} }

      

+5


source


I'm not very familiar with forced geometry, but it looks like you need to iterate over the coordinates at compile time. The way to do this is to create a recursion. The following class apply

will perform this recursion and call the functor on each point coordinate.

All you have to do is write your own functor and overload its () operator if you want to specialize behavior for specific coordinates. The functor in the example below just prints the coordinates and specializes in reading the third coordinate.



#include <boost/geometry.hpp>
#include <iostream>
#include <type_traits>


namespace bg = boost::geometry;

template <int I>
using int_ = std::integral_constant<int, I>;

//recursive call that iterates the point and calls F on its coordinate
template <class Point, class F, std::size_t I = 0>
struct apply {

    static void call(Point& point, F& f) {
        f(point, int_<I>());
        apply<Point, F, I+1>::call(point, f);
    }
};

//specialisation to end the recursion
template <class CT, std::size_t DIM, class S, template <class, std::size_t, class> class Point, class F>
struct apply<Point<CT, DIM, S>, F, DIM> {

    static void call(Point<CT, DIM, S>& point, F& f){}
};

//interface for calling the function
template <class Point, class F>
void apply_functor(Point& point, F& f) {
    apply<Point, F>::call(point, f);
}

//example functor
template <class Point>
struct functor {

    template <class Index>
    void operator()(Point& point, Index I) {
        std::cout << "I am coordinate " << Index::value << " and my value is " << bg::get<Index::value>(point) << std::endl;
    }

//    used for overloading when reading the 3rd coordinate
    void operator()(Point& point, int_<2>) {
        std::cout << "I am coordinate " << 2 << " and I am specialised with value " << bg::get<2>(point) << std::endl;
    }
};


//3-dimensional point type
using point_type = bg::model::point<double, 3, bg::cs::cartesian>;

int main(int argc, char** argv) {
    point_type point(1,2,3);
    functor<point_type> f;
    apply_functor(point, f);

    return 0;
}

      

+2


source







All Articles