/Src/Dependencies/Boost/libs/geometry/example/c08_custom_non_std_example.cpp

http://hadesmem.googlecode.com/ · C++ · 296 lines · 197 code · 65 blank · 34 comment · 11 complexity · bc4139ca2310f68dbada891ff18dac9f MD5 · raw file

  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands.
  3. // Copyright (c) 2008-2011 Bruno Lalande, Paris, France.
  4. // Copyright (c) 2009-2011 Mateusz Loskot, London, UK.
  5. // Use, modification and distribution is subject to the Boost Software License,
  6. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  7. // http://www.boost.org/LICENSE_1_0.txt)
  8. //
  9. // Custom polygon example
  10. #include <iostream>
  11. #include <boost/iterator.hpp>
  12. #include <boost/iterator/iterator_adaptor.hpp>
  13. #include <boost/iterator/iterator_categories.hpp>
  14. #include <boost/iterator/iterator_facade.hpp>
  15. #include <boost/geometry/geometry.hpp>
  16. #include <boost/geometry/geometries/register/point.hpp>
  17. #include <boost/geometry/geometries/register/ring.hpp>
  18. #include <boost/geometry/util/add_const_if_c.hpp>
  19. // Sample point, having x/y
  20. struct my_point
  21. {
  22. my_point(double a = 0, double b = 0)
  23. : x(a), y(b)
  24. {}
  25. double x,y;
  26. };
  27. // Sample polygon, having legacy methods
  28. // (similar to e.g. COM objects)
  29. class my_polygon
  30. {
  31. std::vector<my_point> points;
  32. public :
  33. void add_point(my_point const& p) { points.push_back(p); }
  34. // Const access
  35. my_point const& get_point(std::size_t i) const
  36. {
  37. assert(i < points.size());
  38. return points[i];
  39. }
  40. // Mutable access
  41. my_point & get_point(std::size_t i)
  42. {
  43. assert(i < points.size());
  44. return points[i];
  45. }
  46. int point_count() const { return points.size(); }
  47. void erase_all() { points.clear(); }
  48. inline void set_size(int n) { points.resize(n); }
  49. };
  50. // ----------------------------------------------------------------------------
  51. // Adaption: implement iterator and range-extension, and register with Boost.Geometry
  52. // 1) implement iterator (const and non-const versions)
  53. template <bool IsConst>
  54. struct custom_iterator : public boost::iterator_facade
  55. <
  56. custom_iterator<IsConst>,
  57. my_point,
  58. boost::random_access_traversal_tag,
  59. typename boost::geometry::add_const_if_c<IsConst, my_point>::type&
  60. >
  61. {
  62. // Constructor for begin()
  63. explicit custom_iterator(typename boost::geometry::add_const_if_c<IsConst, my_polygon>::type& polygon)
  64. : m_polygon(&polygon)
  65. , m_index(0)
  66. {}
  67. // Constructor for end()
  68. explicit custom_iterator(bool, typename boost::geometry::add_const_if_c<IsConst, my_polygon>::type& polygon)
  69. : m_polygon(&polygon)
  70. , m_index(polygon.point_count())
  71. {}
  72. private:
  73. friend class boost::iterator_core_access;
  74. typedef boost::iterator_facade
  75. <
  76. custom_iterator<IsConst>,
  77. my_point,
  78. boost::random_access_traversal_tag,
  79. typename boost::geometry::add_const_if_c<IsConst, my_point>::type&
  80. > facade;
  81. typename boost::geometry::add_const_if_c<IsConst, my_polygon>::type* m_polygon;
  82. int m_index;
  83. bool equal(custom_iterator const& other) const
  84. {
  85. return this->m_index == other.m_index;
  86. }
  87. typename facade::difference_type distance_to(custom_iterator const& other) const
  88. {
  89. return other.m_index - this->m_index;
  90. }
  91. void advance(typename facade::difference_type n)
  92. {
  93. m_index += n;
  94. if(m_polygon != NULL
  95. && (m_index >= m_polygon->point_count()
  96. || m_index < 0)
  97. )
  98. {
  99. m_index = m_polygon->point_count();
  100. }
  101. }
  102. void increment()
  103. {
  104. advance(1);
  105. }
  106. void decrement()
  107. {
  108. advance(-1);
  109. }
  110. // const and non-const dereference of this iterator
  111. typename boost::geometry::add_const_if_c<IsConst, my_point>::type& dereference() const
  112. {
  113. return m_polygon->get_point(m_index);
  114. }
  115. };
  116. // 2) Implement Boost.Range const functionality
  117. // using method 2, "provide free-standing functions and specialize metafunctions"
  118. // 2a) meta-functions
  119. namespace boost
  120. {
  121. template<> struct range_mutable_iterator<my_polygon>
  122. {
  123. typedef custom_iterator<false> type;
  124. };
  125. template<> struct range_const_iterator<my_polygon>
  126. {
  127. typedef custom_iterator<true> type;
  128. };
  129. // RangeEx
  130. template<> struct range_size<my_polygon>
  131. {
  132. typedef std::size_t type;
  133. };
  134. } // namespace 'boost'
  135. // 2b) free-standing function for Boost.Range ADP
  136. inline custom_iterator<false> range_begin(my_polygon& polygon)
  137. {
  138. return custom_iterator<false>(polygon);
  139. }
  140. inline custom_iterator<true> range_begin(my_polygon const& polygon)
  141. {
  142. return custom_iterator<true>(polygon);
  143. }
  144. inline custom_iterator<false> range_end(my_polygon& polygon)
  145. {
  146. return custom_iterator<false>(true, polygon);
  147. }
  148. inline custom_iterator<true> range_end(my_polygon const& polygon)
  149. {
  150. return custom_iterator<true>(true, polygon);
  151. }
  152. // 3) optional, for writable geometries only, implement push_back/resize/clear
  153. namespace boost { namespace geometry { namespace traits
  154. {
  155. template<> struct push_back<my_polygon>
  156. {
  157. static inline void apply(my_polygon& polygon, my_point const& point)
  158. {
  159. polygon.add_point(point);
  160. }
  161. };
  162. template<> struct resize<my_polygon>
  163. {
  164. static inline void apply(my_polygon& polygon, std::size_t new_size)
  165. {
  166. polygon.set_size(new_size);
  167. }
  168. };
  169. }}}
  170. // 4) register with Boost.Geometry
  171. BOOST_GEOMETRY_REGISTER_POINT_2D(my_point, double, cs::cartesian, x, y)
  172. BOOST_GEOMETRY_REGISTER_RING(my_polygon)
  173. // end adaption
  174. // ----------------------------------------------------------------------------
  175. void walk_using_iterator(my_polygon const& polygon)
  176. {
  177. for (custom_iterator<true> it = custom_iterator<true>(polygon);
  178. it != custom_iterator<true>(true, polygon);
  179. ++it)
  180. {
  181. std::cout << boost::geometry::dsv(*it) << std::endl;
  182. }
  183. std::cout << std::endl;
  184. }
  185. void walk_using_range(my_polygon const& polygon)
  186. {
  187. for (boost::range_iterator<my_polygon const>::type it
  188. = boost::begin(polygon);
  189. it != boost::end(polygon);
  190. ++it)
  191. {
  192. std::cout << boost::geometry::dsv(*it) << std::endl;
  193. }
  194. std::cout << std::endl;
  195. }
  196. int main()
  197. {
  198. my_polygon container1;
  199. // Create (as an example) a regular polygon
  200. const int n = 5;
  201. const double d = (360 / n) * boost::geometry::math::d2r;
  202. double a = 0;
  203. for (int i = 0; i < n + 1; i++, a += d)
  204. {
  205. container1.add_point(my_point(sin(a), cos(a)));
  206. }
  207. std::cout << "Walk using Boost.Iterator derivative" << std::endl;
  208. walk_using_iterator(container1);
  209. std::cout << "Walk using Boost.Range extension" << std::endl << std::endl;
  210. walk_using_range(container1);
  211. std::cout << "Use it by Boost.Geometry" << std::endl;
  212. std::cout << "Area: " << boost::geometry::area(container1) << std::endl;
  213. // Container 2 will be modified by Boost.Geometry. Add all points but the last one.
  214. my_polygon container2;
  215. for (int i = 0; i < n; i++)
  216. {
  217. // Use here the Boost.Geometry internal way of inserting (but the my_polygon way of getting)
  218. boost::geometry::traits::push_back<my_polygon>::apply(container2, container1.get_point(i));
  219. }
  220. std::cout << "Second container is not closed:" << std::endl;
  221. walk_using_range(container2);
  222. // Correct (= close it)
  223. boost::geometry::correct(container2);
  224. std::cout << "Now it is closed:" << std::endl;
  225. walk_using_range(container2);
  226. std::cout << "Area: " << boost::geometry::area(container2) << std::endl;
  227. // Use things from std:: using Boost.Range
  228. std::reverse(boost::begin(container2), boost::end(container2));
  229. std::cout << "Area reversed: " << boost::geometry::area(container2) << std::endl;
  230. return 0;
  231. }