2017-03-26 100 views
1

的迭代器如何,我可以得到一个协调Point p的迭代器,其中Point正在履行Point Concept坐标点

+1

这似乎不是推荐的方法来处理boost.geometry中的泛型点。你绝对需要一个迭代器吗?如果是这样,不知道你可以做得更好比反覆整数和使用transform_iterator,做'如果(我== 0)得到的回报<0>(P);如果(我== 1)...'。 –

+1

我想计算最小边界球,它尚未在升压几何中实现。因此,我想使用https://people.inf.ethz.ch/gaertner/subdir/software/miniball.html 使用协调迭代器。 – maiermic

回答

0

我需要一个坐标迭代器来使用this库来计算(升压几何体)linestring的点的最小包围球(最小包围球/圆)。以下解决方案最后包含this示例的修改版本:

#include <boost/geometry.hpp> 
#include "Miniball.hpp" 

namespace bg = boost::geometry; 

template<std::size_t> 
struct int2type { 
}; 


template<class Point, std::size_t I> 
typename bg::coordinate_type<Point>::type 
get_imp(std::size_t index, const Point &point, int2type<I>) { 
    return (I == index) 
      ? bg::get<I>(point) 
      : get_imp(index, point, int2type<I - 1>()); 
} 

template<class Point> 
typename bg::coordinate_type<Point>::type 
get_imp(std::size_t index, const Point &point, int2type<0>) { 
    return bg::get<0>(point); 
} 

template<class Point> 
typename bg::coordinate_type<Point>::type 
get(std::size_t index, const Point &point) { 
    static std::size_t const size = bg::dimension<Point>::value; 
    return get_imp(index, point, int2type<size - 1>()); 
} 


template<class Point, std::size_t I> 
void set_imp(std::size_t index, 
      Point &point, 
      typename bg::coordinate_type<Point>::type value, 
      int2type<I>) { 
    return (I == index) 
      ? bg::set<I>(point, value) 
      : set_imp(index, point, value, int2type<I - 1>()); 
} 

template<class Point> 
void set_imp(std::size_t index, 
      Point &point, 
      typename bg::coordinate_type<Point>::type value, 
      int2type<0>) { 
    return bg::set<0>(point, value); 
} 

template<class Point> 
void set(std::size_t index, Point &point, typename bg::coordinate_type<Point>::type value) { 
    static std::size_t const size = bg::dimension<Point>::value; 
    return set_imp(index, point, value, int2type<size - 1>()); 
} 


template<class Point> 
class CoordinateIterator { 
    using self_t = CoordinateIterator<Point>; 

public: 
    using iterator_category = std::forward_iterator_tag; 
    using value_type = typename bg::coordinate_type<Point>::type; 
    using difference_type = std::size_t; 
    using pointer = value_type *; 
    using reference = value_type &; 

private: 
    Point _point; 
    difference_type _pos; 

public: 
    CoordinateIterator() 
      : CoordinateIterator(Point()) {} 

    CoordinateIterator(Point point) 
      : CoordinateIterator(point, 0) {} 

    CoordinateIterator(Point point, difference_type pos) 
      : _point(point), _pos(pos) {} 

    inline value_type operator*() { 
     return get(_pos, _point); 
    } 

    inline const value_type operator*() const { 
     return get(_pos, _point); 
    } 

    inline self_t &operator++() { 
     ++_pos; 
     return *this; 
    } 

    inline self_t operator++(int) { 
     self_t copy(*this); 
     ++_pos; 
     return copy; 
    } 
}; 


template<typename Linestring> 
struct CoordinateAccessor { 
    using Pit = typename Linestring::const_iterator; 
    using Cit = CoordinateIterator<typename bg::point_type<Linestring>::type>; 

    inline Cit operator()(Pit it) const { return Cit(*it); } 
}; 


int main(int argc, char *argv[]) { 
    using point = bg::model::point<double, 2, bg::cs::cartesian>; 
    using linestring = bg::model::linestring<point>; 
    using coordinate_type = bg::coordinate_type<linestring>::type; 
    using PointIterator = CoordinateAccessor<linestring>::Pit; 

    const int dimension = bg::dimension<linestring>::value; 
    const int numberOfPoints = 1000000; 

    // initialize random number generator 
    const double seed = (argc != 2) ? 0 : std::atoi(argv[1]); 
    std::srand(seed); 

    // generate random points and store them in a linestring 
    // ---------------------------------------------------------- 
    linestring line; 
    for (int i = 0; i < numberOfPoints; ++i) { 
     point p; 
     for (int j = 0; j < dimension; ++j) { 
      set(j, p, rand()); 
     } 
     bg::append(line, p); 
    } 

    // create an instance of Miniball 
    // ------------------------------ 
    using MB = Miniball::Miniball<CoordinateAccessor<linestring>>; 
    MB mb(dimension, line.begin(), line.end()); 

    // output results 
    // -------------- 
    // center 
    std::cout << "Center:\n "; 
    const coordinate_type *center = mb.center(); 
    for (int i = 0; i < dimension; ++i, ++center) 
     std::cout << *center << " "; 
    std::cout << std::endl; 

    // squared radius 
    std::cout << "Squared radius:\n "; 
    std::cout << mb.squared_radius() << std::endl; 

    // number of support points 
    std::cout << "Number of support points:\n "; 
    std::cout << mb.nr_support_points() << std::endl; 

    // support points on the boundary determine the smallest enclosing ball 
    std::cout << "Support point indices (numbers refer to the input order):\n "; 
    MB::SupportPointIterator it = mb.support_points_begin(); 
    PointIterator first = line.begin(); 
    for (; it != mb.support_points_end(); ++it) { 
     std::cout << std::distance(first, *it) << " "; // 0 = first point 
    } 
    std::cout << std::endl; 

    // relative error: by how much does the ball fail to contain all points? 
    //     tiny positive numbers come from roundoff and are ok 
    std::cout << "Relative error:\n "; 
    coordinate_type suboptimality; 
    std::cout << mb.relative_error(suboptimality) << std::endl; 

    // suboptimality: by how much does the ball fail to be the smallest 
    //    enclosing ball of its support points? should be 0 
    //    in most cases, but tiny positive numbers are again ok 
    std::cout << "Suboptimality:\n "; 
    std::cout << suboptimality << std::endl; 

    // validity: the ball is considered valid if the relative error is tiny 
    //   (<= 10 times the machine epsilon) and the suboptimality is zero 
    std::cout << "Validity:\n "; 
    std::cout << (mb.is_valid() ? "ok" : "possibly invalid") << std::endl; 

    // computation time 
    std::cout << "Computation time was " << mb.get_time() << " seconds\n"; 

    return 0; 
} 
1

它取决于什么是Point类型。如果您使用bg::model::point<>那么这可能是问题的,因为运行时编译时需要维度指标的翻译,所以如一些数量的for循环或递归函数if条件(如你实现)。

但是,您也可以实现您自己的Point类型并定义您需要的任何成员(例如operator[])或使用已经在另一个库中实现的Point类型(假定最大维度在编译时已知)。然后,让知道Boost.Geometry如何处理点类型你会被迫去适应它通过点对点的概念:

+0

谢谢,好点。这将允许更容易的实施。但是,在我的情况下,我需要一个适用于所有点的解决方案。 – maiermic