for_each.hpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
  3. // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
  4. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
  5. // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
  6. // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
  7. // Use, modification and distribution is subject to the Boost Software License,
  8. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt)
  10. #ifndef BOOST_GEOMETRY_ALGORITHMS_FOR_EACH_HPP
  11. #define BOOST_GEOMETRY_ALGORITHMS_FOR_EACH_HPP
  12. #include <algorithm>
  13. #include <boost/range.hpp>
  14. #include <boost/type_traits/is_const.hpp>
  15. #include <boost/typeof/typeof.hpp>
  16. #include <boost/geometry/algorithms/not_implemented.hpp>
  17. #include <boost/geometry/core/exterior_ring.hpp>
  18. #include <boost/geometry/core/interior_rings.hpp>
  19. #include <boost/geometry/core/tag_cast.hpp>
  20. #include <boost/geometry/geometries/concepts/check.hpp>
  21. #include <boost/geometry/geometries/segment.hpp>
  22. #include <boost/geometry/util/add_const_if_c.hpp>
  23. namespace boost { namespace geometry
  24. {
  25. #ifndef DOXYGEN_NO_DETAIL
  26. namespace detail { namespace for_each
  27. {
  28. struct fe_point_per_point
  29. {
  30. template <typename Point, typename Functor>
  31. static inline void apply(Point& point, Functor& f)
  32. {
  33. f(point);
  34. }
  35. };
  36. struct fe_point_per_segment
  37. {
  38. template <typename Point, typename Functor>
  39. static inline void apply(Point& , Functor& f)
  40. {
  41. // TODO: if non-const, we should extract the points from the segment
  42. // and call the functor on those two points
  43. }
  44. };
  45. struct fe_range_per_point
  46. {
  47. template <typename Range, typename Functor>
  48. static inline void apply(Range& range, Functor& f)
  49. {
  50. // The previous implementation called the std library:
  51. // return (std::for_each(boost::begin(range), boost::end(range), f));
  52. // But that is not accepted for capturing lambda's.
  53. // It needs to do it like that to return the state of Functor f (f is passed by value in std::for_each).
  54. // So we now loop manually.
  55. for (typename boost::range_iterator<Range>::type it = boost::begin(range); it != boost::end(range); ++it)
  56. {
  57. f(*it);
  58. }
  59. }
  60. };
  61. struct fe_range_per_segment
  62. {
  63. template <typename Range, typename Functor>
  64. static inline void apply(Range& range, Functor& f)
  65. {
  66. typedef typename add_const_if_c
  67. <
  68. is_const<Range>::value,
  69. typename point_type<Range>::type
  70. >::type point_type;
  71. BOOST_AUTO_TPL(it, boost::begin(range));
  72. BOOST_AUTO_TPL(previous, it++);
  73. while(it != boost::end(range))
  74. {
  75. model::referring_segment<point_type> s(*previous, *it);
  76. f(s);
  77. previous = it++;
  78. }
  79. }
  80. };
  81. struct fe_polygon_per_point
  82. {
  83. template <typename Polygon, typename Functor>
  84. static inline void apply(Polygon& poly, Functor& f)
  85. {
  86. fe_range_per_point::apply(exterior_ring(poly), f);
  87. typename interior_return_type<Polygon>::type rings
  88. = interior_rings(poly);
  89. for (BOOST_AUTO_TPL(it, boost::begin(rings)); it != boost::end(rings); ++it)
  90. {
  91. fe_range_per_point::apply(*it, f);
  92. }
  93. }
  94. };
  95. struct fe_polygon_per_segment
  96. {
  97. template <typename Polygon, typename Functor>
  98. static inline void apply(Polygon& poly, Functor& f)
  99. {
  100. fe_range_per_segment::apply(exterior_ring(poly), f);
  101. typename interior_return_type<Polygon>::type rings
  102. = interior_rings(poly);
  103. for (BOOST_AUTO_TPL(it, boost::begin(rings)); it != boost::end(rings); ++it)
  104. {
  105. fe_range_per_segment::apply(*it, f);
  106. }
  107. }
  108. };
  109. }} // namespace detail::for_each
  110. #endif // DOXYGEN_NO_DETAIL
  111. #ifndef DOXYGEN_NO_DISPATCH
  112. namespace dispatch
  113. {
  114. template
  115. <
  116. typename Geometry,
  117. typename Tag = typename tag_cast<typename tag<Geometry>::type, multi_tag>::type
  118. >
  119. struct for_each_point: not_implemented<Tag>
  120. {};
  121. template <typename Point>
  122. struct for_each_point<Point, point_tag>
  123. : detail::for_each::fe_point_per_point
  124. {};
  125. template <typename Linestring>
  126. struct for_each_point<Linestring, linestring_tag>
  127. : detail::for_each::fe_range_per_point
  128. {};
  129. template <typename Ring>
  130. struct for_each_point<Ring, ring_tag>
  131. : detail::for_each::fe_range_per_point
  132. {};
  133. template <typename Polygon>
  134. struct for_each_point<Polygon, polygon_tag>
  135. : detail::for_each::fe_polygon_per_point
  136. {};
  137. template
  138. <
  139. typename Geometry,
  140. typename Tag = typename tag_cast<typename tag<Geometry>::type, multi_tag>::type
  141. >
  142. struct for_each_segment: not_implemented<Tag>
  143. {};
  144. template <typename Point>
  145. struct for_each_segment<Point, point_tag>
  146. : detail::for_each::fe_point_per_segment
  147. {};
  148. template <typename Linestring>
  149. struct for_each_segment<Linestring, linestring_tag>
  150. : detail::for_each::fe_range_per_segment
  151. {};
  152. template <typename Ring>
  153. struct for_each_segment<Ring, ring_tag>
  154. : detail::for_each::fe_range_per_segment
  155. {};
  156. template <typename Polygon>
  157. struct for_each_segment<Polygon, polygon_tag>
  158. : detail::for_each::fe_polygon_per_segment
  159. {};
  160. } // namespace dispatch
  161. #endif // DOXYGEN_NO_DISPATCH
  162. /*!
  163. \brief \brf_for_each{point}
  164. \details \det_for_each{point}
  165. \ingroup for_each
  166. \param geometry \param_geometry
  167. \param f \par_for_each_f{point}
  168. \tparam Geometry \tparam_geometry
  169. \tparam Functor \tparam_functor
  170. \qbk{[include reference/algorithms/for_each_point.qbk]}
  171. \qbk{[heading Example]}
  172. \qbk{[for_each_point] [for_each_point_output]}
  173. \qbk{[for_each_point_const] [for_each_point_const_output]}
  174. */
  175. template<typename Geometry, typename Functor>
  176. inline Functor for_each_point(Geometry& geometry, Functor f)
  177. {
  178. concept::check<Geometry>();
  179. dispatch::for_each_point<Geometry>::apply(geometry, f);
  180. return f;
  181. }
  182. /*!
  183. \brief \brf_for_each{segment}
  184. \details \det_for_each{segment}
  185. \ingroup for_each
  186. \param geometry \param_geometry
  187. \param f \par_for_each_f{segment}
  188. \tparam Geometry \tparam_geometry
  189. \tparam Functor \tparam_functor
  190. \qbk{[include reference/algorithms/for_each_segment.qbk]}
  191. \qbk{[heading Example]}
  192. \qbk{[for_each_segment_const] [for_each_segment_const_output]}
  193. */
  194. template<typename Geometry, typename Functor>
  195. inline Functor for_each_segment(Geometry& geometry, Functor f)
  196. {
  197. concept::check<Geometry>();
  198. dispatch::for_each_segment<Geometry>::apply(geometry, f);
  199. return f;
  200. }
  201. }} // namespace boost::geometry
  202. #endif // BOOST_GEOMETRY_ALGORITHMS_FOR_EACH_HPP