num_points.hpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  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_NUM_POINTS_HPP
  11. #define BOOST_GEOMETRY_ALGORITHMS_NUM_POINTS_HPP
  12. #include <cstddef>
  13. #include <boost/range.hpp>
  14. #include <boost/typeof/typeof.hpp>
  15. #include <boost/geometry/core/closure.hpp>
  16. #include <boost/geometry/core/exterior_ring.hpp>
  17. #include <boost/geometry/core/interior_rings.hpp>
  18. #include <boost/geometry/core/tag_cast.hpp>
  19. #include <boost/geometry/algorithms/disjoint.hpp>
  20. #include <boost/geometry/algorithms/not_implemented.hpp>
  21. #include <boost/geometry/geometries/concepts/check.hpp>
  22. #include <boost/variant/static_visitor.hpp>
  23. #include <boost/variant/apply_visitor.hpp>
  24. #include <boost/variant/variant_fwd.hpp>
  25. namespace boost { namespace geometry
  26. {
  27. // Silence warning C4127: conditional expression is constant
  28. #if defined(_MSC_VER)
  29. #pragma warning(push)
  30. #pragma warning(disable : 4127)
  31. #endif
  32. #ifndef DOXYGEN_NO_DETAIL
  33. namespace detail { namespace num_points
  34. {
  35. struct range_count
  36. {
  37. template <typename Range>
  38. static inline std::size_t apply(Range const& range, bool add_for_open)
  39. {
  40. std::size_t n = boost::size(range);
  41. if (add_for_open && n > 0)
  42. {
  43. if (geometry::closure<Range>::value == open)
  44. {
  45. if (geometry::disjoint(*boost::begin(range), *(boost::begin(range) + n - 1)))
  46. {
  47. return n + 1;
  48. }
  49. }
  50. }
  51. return n;
  52. }
  53. };
  54. template <std::size_t D>
  55. struct other_count
  56. {
  57. template <typename Geometry>
  58. static inline std::size_t apply(Geometry const&, bool)
  59. {
  60. return D;
  61. }
  62. };
  63. struct polygon_count: private range_count
  64. {
  65. template <typename Polygon>
  66. static inline std::size_t apply(Polygon const& poly, bool add_for_open)
  67. {
  68. std::size_t n = range_count::apply(
  69. exterior_ring(poly), add_for_open);
  70. typename interior_return_type<Polygon const>::type rings
  71. = interior_rings(poly);
  72. for (BOOST_AUTO_TPL(it, boost::begin(rings)); it != boost::end(rings); ++it)
  73. {
  74. n += range_count::apply(*it, add_for_open);
  75. }
  76. return n;
  77. }
  78. };
  79. }} // namespace detail::num_points
  80. #endif // DOXYGEN_NO_DETAIL
  81. #ifndef DOXYGEN_NO_DISPATCH
  82. namespace dispatch
  83. {
  84. template
  85. <
  86. typename Geometry,
  87. typename Tag = typename tag_cast<typename tag<Geometry>::type, multi_tag>::type
  88. >
  89. struct num_points: not_implemented<Tag>
  90. {};
  91. template <typename Geometry>
  92. struct num_points<Geometry, point_tag>
  93. : detail::num_points::other_count<1>
  94. {};
  95. template <typename Geometry>
  96. struct num_points<Geometry, box_tag>
  97. : detail::num_points::other_count<4>
  98. {};
  99. template <typename Geometry>
  100. struct num_points<Geometry, segment_tag>
  101. : detail::num_points::other_count<2>
  102. {};
  103. template <typename Geometry>
  104. struct num_points<Geometry, linestring_tag>
  105. : detail::num_points::range_count
  106. {};
  107. template <typename Geometry>
  108. struct num_points<Geometry, ring_tag>
  109. : detail::num_points::range_count
  110. {};
  111. template <typename Geometry>
  112. struct num_points<Geometry, polygon_tag>
  113. : detail::num_points::polygon_count
  114. {};
  115. template <typename Geometry>
  116. struct devarianted_num_points
  117. {
  118. static inline std::size_t apply(Geometry const& geometry,
  119. bool add_for_open)
  120. {
  121. return num_points<Geometry>::apply(geometry, add_for_open);
  122. }
  123. };
  124. template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
  125. struct devarianted_num_points<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
  126. {
  127. struct visitor: boost::static_visitor<std::size_t>
  128. {
  129. bool m_add_for_open;
  130. visitor(bool add_for_open): m_add_for_open(add_for_open) {}
  131. template <typename Geometry>
  132. typename std::size_t operator()(Geometry const& geometry) const
  133. {
  134. return dispatch::num_points<Geometry>::apply(geometry, m_add_for_open);
  135. }
  136. };
  137. static inline std::size_t
  138. apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
  139. bool add_for_open)
  140. {
  141. return boost::apply_visitor(visitor(add_for_open), geometry);
  142. }
  143. };
  144. } // namespace dispatch
  145. #endif
  146. /*!
  147. \brief \brief_calc{number of points}
  148. \ingroup num_points
  149. \details \details_calc{num_points, number of points}.
  150. \tparam Geometry \tparam_geometry
  151. \param geometry \param_geometry
  152. \param add_for_open add one for open geometries (i.e. polygon types which are not closed)
  153. \return \return_calc{number of points}
  154. \qbk{[include reference/algorithms/num_points.qbk]}
  155. */
  156. template <typename Geometry>
  157. inline std::size_t num_points(Geometry const& geometry, bool add_for_open = false)
  158. {
  159. concept::check<Geometry const>();
  160. return dispatch::devarianted_num_points<Geometry>::apply(geometry, add_for_open);
  161. }
  162. #if defined(_MSC_VER)
  163. #pragma warning(pop)
  164. #endif
  165. }} // namespace boost::geometry
  166. #endif // BOOST_GEOMETRY_ALGORITHMS_NUM_POINTS_HPP