arithmetic.hpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
  3. // Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.
  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_ARITHMETIC_ARITHMETIC_HPP
  11. #define BOOST_GEOMETRY_ARITHMETIC_ARITHMETIC_HPP
  12. #include <functional>
  13. #include <boost/call_traits.hpp>
  14. #include <boost/concept/requires.hpp>
  15. #include <boost/geometry/core/coordinate_type.hpp>
  16. #include <boost/geometry/geometries/concepts/point_concept.hpp>
  17. #include <boost/geometry/util/for_each_coordinate.hpp>
  18. namespace boost { namespace geometry
  19. {
  20. #ifndef DOXYGEN_NO_DETAIL
  21. namespace detail
  22. {
  23. template <typename P>
  24. struct param
  25. {
  26. typedef typename boost::call_traits
  27. <
  28. typename coordinate_type<P>::type
  29. >::param_type type;
  30. };
  31. template <typename C, template <typename> class Function>
  32. struct value_operation
  33. {
  34. C m_value;
  35. inline value_operation(C const &value)
  36. : m_value(value)
  37. {}
  38. template <typename P, int I>
  39. inline void apply(P& point) const
  40. {
  41. set<I>(point, Function<C>()(get<I>(point), m_value));
  42. }
  43. };
  44. template <typename PointSrc, template <typename> class Function>
  45. struct point_operation
  46. {
  47. typedef typename coordinate_type<PointSrc>::type coordinate_type;
  48. PointSrc const& m_source_point;
  49. inline point_operation(PointSrc const& point)
  50. : m_source_point(point)
  51. {}
  52. template <typename PointDst, int I>
  53. inline void apply(PointDst& dest_point) const
  54. {
  55. set<I>(dest_point,
  56. Function<coordinate_type>()(get<I>(dest_point), get<I>(m_source_point)));
  57. }
  58. };
  59. template <typename C>
  60. struct value_assignment
  61. {
  62. C m_value;
  63. inline value_assignment(C const &value)
  64. : m_value(value)
  65. {}
  66. template <typename P, int I>
  67. inline void apply(P& point) const
  68. {
  69. set<I>(point, m_value);
  70. }
  71. };
  72. template <typename PointSrc>
  73. struct point_assignment
  74. {
  75. PointSrc const& m_source_point;
  76. inline point_assignment(PointSrc const& point)
  77. : m_source_point(point)
  78. {}
  79. template <typename PointDst, int I>
  80. inline void apply(PointDst& dest_point) const
  81. {
  82. set<I>(dest_point, get<I>(m_source_point));
  83. }
  84. };
  85. } // namespace detail
  86. #endif // DOXYGEN_NO_DETAIL
  87. /*!
  88. \brief Adds the same value to each coordinate of a point
  89. \ingroup arithmetic
  90. \details
  91. \param p point
  92. \param value value to add
  93. */
  94. template <typename Point>
  95. inline void add_value(Point& p, typename detail::param<Point>::type value)
  96. {
  97. BOOST_CONCEPT_ASSERT( (concept::Point<Point>) );
  98. for_each_coordinate(p, detail::value_operation<typename coordinate_type<Point>::type, std::plus>(value));
  99. }
  100. /*!
  101. \brief Adds a point to another
  102. \ingroup arithmetic
  103. \details The coordinates of the second point will be added to those of the first point.
  104. The second point is not modified.
  105. \param p1 first point
  106. \param p2 second point
  107. */
  108. template <typename Point1, typename Point2>
  109. inline void add_point(Point1& p1, Point2 const& p2)
  110. {
  111. BOOST_CONCEPT_ASSERT( (concept::Point<Point2>) );
  112. BOOST_CONCEPT_ASSERT( (concept::ConstPoint<Point2>) );
  113. for_each_coordinate(p1, detail::point_operation<Point2, std::plus>(p2));
  114. }
  115. /*!
  116. \brief Subtracts the same value to each coordinate of a point
  117. \ingroup arithmetic
  118. \details
  119. \param p point
  120. \param value value to subtract
  121. */
  122. template <typename Point>
  123. inline void subtract_value(Point& p, typename detail::param<Point>::type value)
  124. {
  125. BOOST_CONCEPT_ASSERT( (concept::Point<Point>) );
  126. for_each_coordinate(p, detail::value_operation<typename coordinate_type<Point>::type, std::minus>(value));
  127. }
  128. /*!
  129. \brief Subtracts a point to another
  130. \ingroup arithmetic
  131. \details The coordinates of the second point will be subtracted to those of the first point.
  132. The second point is not modified.
  133. \param p1 first point
  134. \param p2 second point
  135. */
  136. template <typename Point1, typename Point2>
  137. inline void subtract_point(Point1& p1, Point2 const& p2)
  138. {
  139. BOOST_CONCEPT_ASSERT( (concept::Point<Point2>) );
  140. BOOST_CONCEPT_ASSERT( (concept::ConstPoint<Point2>) );
  141. for_each_coordinate(p1, detail::point_operation<Point2, std::minus>(p2));
  142. }
  143. /*!
  144. \brief Multiplies each coordinate of a point by the same value
  145. \ingroup arithmetic
  146. \details
  147. \param p point
  148. \param value value to multiply by
  149. */
  150. template <typename Point>
  151. inline void multiply_value(Point& p, typename detail::param<Point>::type value)
  152. {
  153. BOOST_CONCEPT_ASSERT( (concept::Point<Point>) );
  154. for_each_coordinate(p, detail::value_operation<typename coordinate_type<Point>::type, std::multiplies>(value));
  155. }
  156. /*!
  157. \brief Multiplies a point by another
  158. \ingroup arithmetic
  159. \details The coordinates of the first point will be multiplied by those of the second point.
  160. The second point is not modified.
  161. \param p1 first point
  162. \param p2 second point
  163. \note This is *not* a dot, cross or wedge product. It is a mere field-by-field multiplication.
  164. */
  165. template <typename Point1, typename Point2>
  166. inline void multiply_point(Point1& p1, Point2 const& p2)
  167. {
  168. BOOST_CONCEPT_ASSERT( (concept::Point<Point2>) );
  169. BOOST_CONCEPT_ASSERT( (concept::ConstPoint<Point2>) );
  170. for_each_coordinate(p1, detail::point_operation<Point2, std::multiplies>(p2));
  171. }
  172. /*!
  173. \brief Divides each coordinate of the same point by a value
  174. \ingroup arithmetic
  175. \details
  176. \param p point
  177. \param value value to divide by
  178. */
  179. template <typename Point>
  180. inline void divide_value(Point& p, typename detail::param<Point>::type value)
  181. {
  182. BOOST_CONCEPT_ASSERT( (concept::Point<Point>) );
  183. for_each_coordinate(p, detail::value_operation<typename coordinate_type<Point>::type, std::divides>(value));
  184. }
  185. /*!
  186. \brief Divides a point by another
  187. \ingroup arithmetic
  188. \details The coordinates of the first point will be divided by those of the second point.
  189. The second point is not modified.
  190. \param p1 first point
  191. \param p2 second point
  192. */
  193. template <typename Point1, typename Point2>
  194. inline void divide_point(Point1& p1, Point2 const& p2)
  195. {
  196. BOOST_CONCEPT_ASSERT( (concept::Point<Point2>) );
  197. BOOST_CONCEPT_ASSERT( (concept::ConstPoint<Point2>) );
  198. for_each_coordinate(p1, detail::point_operation<Point2, std::divides>(p2));
  199. }
  200. /*!
  201. \brief Assign each coordinate of a point the same value
  202. \ingroup arithmetic
  203. \details
  204. \param p point
  205. \param value value to assign
  206. */
  207. template <typename Point>
  208. inline void assign_value(Point& p, typename detail::param<Point>::type value)
  209. {
  210. BOOST_CONCEPT_ASSERT( (concept::Point<Point>) );
  211. for_each_coordinate(p, detail::value_assignment<typename coordinate_type<Point>::type>(value));
  212. }
  213. /*!
  214. \brief Assign a point with another
  215. \ingroup arithmetic
  216. \details The coordinates of the first point will be assigned those of the second point.
  217. The second point is not modified.
  218. \param p1 first point
  219. \param p2 second point
  220. */
  221. template <typename Point1, typename Point2>
  222. inline void assign_point(Point1& p1, const Point2& p2)
  223. {
  224. BOOST_CONCEPT_ASSERT( (concept::Point<Point2>) );
  225. BOOST_CONCEPT_ASSERT( (concept::ConstPoint<Point2>) );
  226. for_each_coordinate(p1, detail::point_assignment<Point2>(p2));
  227. }
  228. }} // namespace boost::geometry
  229. #endif // BOOST_GEOMETRY_ARITHMETIC_ARITHMETIC_HPP