arithmetic.hpp 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  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. #include <boost/geometry/util/select_most_precise.hpp>
  19. namespace boost { namespace geometry
  20. {
  21. #ifndef DOXYGEN_NO_DETAIL
  22. namespace detail
  23. {
  24. template <typename Point>
  25. struct param
  26. {
  27. typedef typename boost::call_traits
  28. <
  29. typename coordinate_type<Point>::type
  30. >::param_type type;
  31. };
  32. template <typename Value, template <typename> class Function>
  33. struct value_operation
  34. {
  35. Value m_value;
  36. inline value_operation(Value const &value)
  37. : m_value(value)
  38. {}
  39. template <typename PointDst, std::size_t Index>
  40. inline void apply(PointDst& point_dst) const
  41. {
  42. set<Index>(point_dst,
  43. Function
  44. <
  45. typename geometry::select_most_precise
  46. <
  47. Value,
  48. typename geometry::coordinate_type<PointDst>::type
  49. >::type
  50. >()(get<Index>(point_dst), m_value));
  51. }
  52. };
  53. template <typename PointSrc, template <typename> class Function>
  54. struct point_operation
  55. {
  56. PointSrc const& m_point_src;
  57. inline point_operation(PointSrc const& point)
  58. : m_point_src(point)
  59. {}
  60. template <typename PointDst, std::size_t Index>
  61. inline void apply(PointDst& point_dst) const
  62. {
  63. set<Index>(point_dst,
  64. Function
  65. <
  66. typename geometry::select_most_precise
  67. <
  68. typename geometry::coordinate_type<PointSrc>::type,
  69. typename geometry::coordinate_type<PointDst>::type
  70. >::type
  71. >()(get<Index>(point_dst), get<Index>(m_point_src)));
  72. }
  73. };
  74. template <typename Value>
  75. struct value_assignment
  76. {
  77. Value m_value;
  78. inline value_assignment(Value const &value)
  79. : m_value(value)
  80. {}
  81. template <typename PointDst, std::size_t Index>
  82. inline void apply(PointDst& point_dst) const
  83. {
  84. set<Index>(point_dst, m_value);
  85. }
  86. };
  87. template <typename PointSrc>
  88. struct point_assignment
  89. {
  90. PointSrc const& m_point_src;
  91. inline point_assignment(PointSrc const& point)
  92. : m_point_src(point)
  93. {}
  94. template <typename PointDst, std::size_t Index>
  95. inline void apply(PointDst& point_dst) const
  96. {
  97. set<Index>(point_dst, get<Index>(m_point_src));
  98. }
  99. };
  100. } // namespace detail
  101. #endif // DOXYGEN_NO_DETAIL
  102. /*!
  103. \brief Adds the same value to each coordinate of a point
  104. \ingroup arithmetic
  105. \details
  106. \tparam Point \tparam_point
  107. \param p point
  108. \param value value to add
  109. */
  110. template <typename Point>
  111. inline void add_value(Point& p, typename detail::param<Point>::type value)
  112. {
  113. BOOST_CONCEPT_ASSERT( (concepts::Point<Point>) );
  114. for_each_coordinate(p,
  115. detail::value_operation
  116. <
  117. typename coordinate_type<Point>::type,
  118. std::plus
  119. >(value));
  120. }
  121. /*!
  122. \brief Adds a point to another
  123. \ingroup arithmetic
  124. \details The coordinates of the second point will be added to those of the first point.
  125. The second point is not modified.
  126. \tparam Point1 \tparam_point
  127. \tparam Point2 \tparam_point
  128. \param p1 first point
  129. \param p2 second point
  130. */
  131. template <typename Point1, typename Point2>
  132. inline void add_point(Point1& p1, Point2 const& p2)
  133. {
  134. BOOST_CONCEPT_ASSERT( (concepts::Point<Point1>) );
  135. BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<Point2>) );
  136. for_each_coordinate(p1, detail::point_operation<Point2, std::plus>(p2));
  137. }
  138. /*!
  139. \brief Subtracts the same value to each coordinate of a point
  140. \ingroup arithmetic
  141. \details
  142. \tparam Point \tparam_point
  143. \param p point
  144. \param value value to subtract
  145. */
  146. template <typename Point>
  147. inline void subtract_value(Point& p, typename detail::param<Point>::type value)
  148. {
  149. BOOST_CONCEPT_ASSERT( (concepts::Point<Point>) );
  150. for_each_coordinate(p,
  151. detail::value_operation
  152. <
  153. typename coordinate_type<Point>::type,
  154. std::minus
  155. >(value));
  156. }
  157. /*!
  158. \brief Subtracts a point to another
  159. \ingroup arithmetic
  160. \details The coordinates of the second point will be subtracted to those of the first point.
  161. The second point is not modified.
  162. \tparam Point1 \tparam_point
  163. \tparam Point2 \tparam_point
  164. \param p1 first point
  165. \param p2 second point
  166. */
  167. template <typename Point1, typename Point2>
  168. inline void subtract_point(Point1& p1, Point2 const& p2)
  169. {
  170. BOOST_CONCEPT_ASSERT( (concepts::Point<Point1>) );
  171. BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<Point2>) );
  172. for_each_coordinate(p1, detail::point_operation<Point2, std::minus>(p2));
  173. }
  174. /*!
  175. \brief Multiplies each coordinate of a point by the same value
  176. \ingroup arithmetic
  177. \details
  178. \tparam Point \tparam_point
  179. \param p point
  180. \param value value to multiply by
  181. */
  182. template <typename Point>
  183. inline void multiply_value(Point& p, typename detail::param<Point>::type value)
  184. {
  185. BOOST_CONCEPT_ASSERT( (concepts::Point<Point>) );
  186. for_each_coordinate(p,
  187. detail::value_operation
  188. <
  189. typename coordinate_type<Point>::type,
  190. std::multiplies
  191. >(value));
  192. }
  193. /*!
  194. \brief Multiplies a point by another
  195. \ingroup arithmetic
  196. \details The coordinates of the first point will be multiplied by those of the second point.
  197. The second point is not modified.
  198. \tparam Point1 \tparam_point
  199. \tparam Point2 \tparam_point
  200. \param p1 first point
  201. \param p2 second point
  202. \note This is *not* a dot, cross or wedge product. It is a mere field-by-field multiplication.
  203. */
  204. template <typename Point1, typename Point2>
  205. inline void multiply_point(Point1& p1, Point2 const& p2)
  206. {
  207. BOOST_CONCEPT_ASSERT( (concepts::Point<Point1>) );
  208. BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<Point2>) );
  209. for_each_coordinate(p1, detail::point_operation<Point2, std::multiplies>(p2));
  210. }
  211. /*!
  212. \brief Divides each coordinate of the same point by a value
  213. \ingroup arithmetic
  214. \details
  215. \tparam Point \tparam_point
  216. \param p point
  217. \param value value to divide by
  218. */
  219. template <typename Point>
  220. inline void divide_value(Point& p, typename detail::param<Point>::type value)
  221. {
  222. BOOST_CONCEPT_ASSERT( (concepts::Point<Point>) );
  223. for_each_coordinate(p,
  224. detail::value_operation
  225. <
  226. typename coordinate_type<Point>::type,
  227. std::divides
  228. >(value));
  229. }
  230. /*!
  231. \brief Divides a point by another
  232. \ingroup arithmetic
  233. \details The coordinates of the first point will be divided by those of the second point.
  234. The second point is not modified.
  235. \tparam Point1 \tparam_point
  236. \tparam Point2 \tparam_point
  237. \param p1 first point
  238. \param p2 second point
  239. */
  240. template <typename Point1, typename Point2>
  241. inline void divide_point(Point1& p1, Point2 const& p2)
  242. {
  243. BOOST_CONCEPT_ASSERT( (concepts::Point<Point1>) );
  244. BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<Point2>) );
  245. for_each_coordinate(p1, detail::point_operation<Point2, std::divides>(p2));
  246. }
  247. /*!
  248. \brief Assign each coordinate of a point the same value
  249. \ingroup arithmetic
  250. \details
  251. \tparam Point \tparam_point
  252. \param p point
  253. \param value value to assign
  254. */
  255. template <typename Point>
  256. inline void assign_value(Point& p, typename detail::param<Point>::type value)
  257. {
  258. BOOST_CONCEPT_ASSERT( (concepts::Point<Point>) );
  259. for_each_coordinate(p,
  260. detail::value_assignment
  261. <
  262. typename coordinate_type<Point>::type
  263. >(value));
  264. }
  265. /*!
  266. \brief Assign a point with another
  267. \ingroup arithmetic
  268. \details The coordinates of the first point will be assigned those of the second point.
  269. The second point is not modified.
  270. \tparam Point1 \tparam_point
  271. \tparam Point2 \tparam_point
  272. \param p1 first point
  273. \param p2 second point
  274. */
  275. template <typename Point1, typename Point2>
  276. inline void assign_point(Point1& p1, Point2 const& p2)
  277. {
  278. BOOST_CONCEPT_ASSERT( (concepts::Point<Point1>) );
  279. BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<Point2>) );
  280. for_each_coordinate(p1, detail::point_assignment<Point2>(p2));
  281. }
  282. }} // namespace boost::geometry
  283. #endif // BOOST_GEOMETRY_ARITHMETIC_ARITHMETIC_HPP