PageRenderTime 73ms CodeModel.GetById 48ms RepoModel.GetById 1ms app.codeStats 0ms

/Mobile Host/jni/boost/geometry/strategies/strategy_transform.hpp

https://bitbucket.org/mobilecloudlab/mobilehostdist
C++ Header | 443 lines | 279 code | 79 blank | 85 comment | 2 complexity | f089871fe0ac3995c43aeb907d903b0f 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. // 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_STRATEGIES_STRATEGY_TRANSFORM_HPP
  11. #define BOOST_GEOMETRY_STRATEGIES_STRATEGY_TRANSFORM_HPP
  12. #include <cstddef>
  13. #include <cmath>
  14. #include <functional>
  15. #include <boost/numeric/conversion/cast.hpp>
  16. #include <boost/geometry/algorithms/convert.hpp>
  17. #include <boost/geometry/arithmetic/arithmetic.hpp>
  18. #include <boost/geometry/core/access.hpp>
  19. #include <boost/geometry/core/coordinate_dimension.hpp>
  20. #include <boost/geometry/util/math.hpp>
  21. #include <boost/geometry/util/select_coordinate_type.hpp>
  22. namespace boost { namespace geometry
  23. {
  24. namespace strategy { namespace transform
  25. {
  26. #ifndef DOXYGEN_NO_DETAIL
  27. namespace detail
  28. {
  29. template
  30. <
  31. typename Src, typename Dst,
  32. std::size_t D, std::size_t N,
  33. template <typename> class F
  34. >
  35. struct transform_coordinates
  36. {
  37. template <typename T>
  38. static inline void transform(Src const& source, Dst& dest, T value)
  39. {
  40. typedef typename select_coordinate_type<Src, Dst>::type coordinate_type;
  41. F<coordinate_type> function;
  42. set<D>(dest, boost::numeric_cast<coordinate_type>(function(get<D>(source), value)));
  43. transform_coordinates<Src, Dst, D + 1, N, F>::transform(source, dest, value);
  44. }
  45. };
  46. template
  47. <
  48. typename Src, typename Dst,
  49. std::size_t N,
  50. template <typename> class F
  51. >
  52. struct transform_coordinates<Src, Dst, N, N, F>
  53. {
  54. template <typename T>
  55. static inline void transform(Src const& source, Dst& dest, T value)
  56. {
  57. }
  58. };
  59. } // namespace detail
  60. #endif // DOXYGEN_NO_DETAIL
  61. /*!
  62. \brief Transformation strategy to copy one point to another using assignment operator
  63. \ingroup transform
  64. \tparam P point type
  65. */
  66. template <typename P>
  67. struct copy_direct
  68. {
  69. inline bool apply(P const& p1, P& p2) const
  70. {
  71. p2 = p1;
  72. return true;
  73. }
  74. };
  75. /*!
  76. \brief Transformation strategy to do copy a point, copying per coordinate.
  77. \ingroup transform
  78. \tparam P1 first point type
  79. \tparam P2 second point type
  80. */
  81. template <typename P1, typename P2>
  82. struct copy_per_coordinate
  83. {
  84. inline bool apply(P1 const& p1, P2& p2) const
  85. {
  86. // Defensive check, dimensions are equal, selected by specialization
  87. assert_dimension_equal<P1, P2>();
  88. geometry::convert(p1, p2);
  89. return true;
  90. }
  91. };
  92. /*!
  93. \brief Transformation strategy to go from degree to radian and back
  94. \ingroup transform
  95. \tparam P1 first point type
  96. \tparam P2 second point type
  97. \tparam F additional functor to divide or multiply with d2r
  98. */
  99. template <typename P1, typename P2, template <typename> class F>
  100. struct degree_radian_vv
  101. {
  102. inline bool apply(P1 const& p1, P2& p2) const
  103. {
  104. // Spherical coordinates always have 2 coordinates measured in angles
  105. // The optional third one is distance/height, provided in another strategy
  106. // Polar coordinates having one angle, will be also in another strategy
  107. assert_dimension<P1, 2>();
  108. assert_dimension<P2, 2>();
  109. detail::transform_coordinates<P1, P2, 0, 2, F>::transform(p1, p2, math::d2r);
  110. return true;
  111. }
  112. };
  113. template <typename P1, typename P2, template <typename> class F>
  114. struct degree_radian_vv_3
  115. {
  116. inline bool apply(P1 const& p1, P2& p2) const
  117. {
  118. assert_dimension<P1, 3>();
  119. assert_dimension<P2, 3>();
  120. detail::transform_coordinates<P1, P2, 0, 2, F>::transform(p1, p2, math::d2r);
  121. // Copy height or other third dimension
  122. set<2>(p2, get<2>(p1));
  123. return true;
  124. }
  125. };
  126. #ifndef DOXYGEN_NO_DETAIL
  127. namespace detail
  128. {
  129. /// Helper function for conversion, phi/theta are in radians
  130. template <typename P, typename T, typename R>
  131. inline void spherical_polar_to_cartesian(T phi, T theta, R r, P& p)
  132. {
  133. assert_dimension<P, 3>();
  134. // http://en.wikipedia.org/wiki/List_of_canonical_coordinate_transformations#From_spherical_coordinates
  135. // http://www.vias.org/comp_geometry/math_coord_convert_3d.htm
  136. // https://moodle.polymtl.ca/file.php/1183/Autres_Documents/Derivation_for_Spherical_Co-ordinates.pdf
  137. // http://en.citizendium.org/wiki/Spherical_polar_coordinates
  138. // Phi = first, theta is second, r is third, see documentation on cs::spherical
  139. // (calculations are splitted to implement ttmath)
  140. T r_sin_theta = r;
  141. T r_cos_theta = r;
  142. r_sin_theta *= sin(theta);
  143. r_cos_theta *= cos(theta);
  144. set<0>(p, r_sin_theta * cos(phi));
  145. set<1>(p, r_sin_theta * sin(phi));
  146. set<2>(p, r_cos_theta);
  147. }
  148. /// Helper function for conversion, lambda/delta (lon lat) are in radians
  149. template <typename P, typename T, typename R>
  150. inline void spherical_equatorial_to_cartesian(T lambda, T delta, R r, P& p)
  151. {
  152. assert_dimension<P, 3>();
  153. // http://mathworld.wolfram.com/GreatCircle.html
  154. // http://www.spenvis.oma.be/help/background/coortran/coortran.html WRONG
  155. T r_cos_delta = r;
  156. T r_sin_delta = r;
  157. r_cos_delta *= cos(delta);
  158. r_sin_delta *= sin(delta);
  159. set<0>(p, r_cos_delta * cos(lambda));
  160. set<1>(p, r_cos_delta * sin(lambda));
  161. set<2>(p, r_sin_delta);
  162. }
  163. /// Helper function for conversion
  164. template <typename P, typename T>
  165. inline bool cartesian_to_spherical2(T x, T y, T z, P& p)
  166. {
  167. assert_dimension<P, 2>();
  168. // http://en.wikipedia.org/wiki/List_of_canonical_coordinate_transformations#From_Cartesian_coordinates
  169. #if defined(BOOST_GEOMETRY_TRANSFORM_CHECK_UNIT_SPHERE)
  170. // TODO: MAYBE ONLY IF TO BE CHECKED?
  171. T const r = /*sqrt not necessary, sqrt(1)=1*/ (x * x + y * y + z * z);
  172. // Unit sphere, so r should be 1
  173. if (geometry::math::abs(r - 1.0) > T(1e-6))
  174. {
  175. return false;
  176. }
  177. // end todo
  178. #endif
  179. set_from_radian<0>(p, atan2(y, x));
  180. set_from_radian<1>(p, acos(z));
  181. return true;
  182. }
  183. template <typename P, typename T>
  184. inline bool cartesian_to_spherical3(T x, T y, T z, P& p)
  185. {
  186. assert_dimension<P, 3>();
  187. // http://en.wikipedia.org/wiki/List_of_canonical_coordinate_transformations#From_Cartesian_coordinates
  188. T const r = sqrt(x * x + y * y + z * z);
  189. set<2>(p, r);
  190. set_from_radian<0>(p, atan2(y, x));
  191. if (r > 0.0)
  192. {
  193. set_from_radian<1>(p, acos(z / r));
  194. return true;
  195. }
  196. return false;
  197. }
  198. } // namespace detail
  199. #endif // DOXYGEN_NO_DETAIL
  200. /*!
  201. \brief Transformation strategy for 2D spherical (phi,theta) to 3D cartesian (x,y,z)
  202. \details on Unit sphere
  203. \ingroup transform
  204. \tparam P1 first point type
  205. \tparam P2 second point type
  206. */
  207. template <typename P1, typename P2>
  208. struct from_spherical_polar_2_to_cartesian_3
  209. {
  210. inline bool apply(P1 const& p1, P2& p2) const
  211. {
  212. assert_dimension<P1, 2>();
  213. detail::spherical_polar_to_cartesian(get_as_radian<0>(p1), get_as_radian<1>(p1), 1.0, p2);
  214. return true;
  215. }
  216. };
  217. template <typename P1, typename P2>
  218. struct from_spherical_equatorial_2_to_cartesian_3
  219. {
  220. inline bool apply(P1 const& p1, P2& p2) const
  221. {
  222. assert_dimension<P1, 2>();
  223. detail::spherical_equatorial_to_cartesian(get_as_radian<0>(p1), get_as_radian<1>(p1), 1.0, p2);
  224. return true;
  225. }
  226. };
  227. /*!
  228. \brief Transformation strategy for 3D spherical (phi,theta,r) to 3D cartesian (x,y,z)
  229. \ingroup transform
  230. \tparam P1 first point type
  231. \tparam P2 second point type
  232. */
  233. template <typename P1, typename P2>
  234. struct from_spherical_polar_3_to_cartesian_3
  235. {
  236. inline bool apply(P1 const& p1, P2& p2) const
  237. {
  238. assert_dimension<P1, 3>();
  239. detail::spherical_polar_to_cartesian(
  240. get_as_radian<0>(p1), get_as_radian<1>(p1), get<2>(p1), p2);
  241. return true;
  242. }
  243. };
  244. template <typename P1, typename P2>
  245. struct from_spherical_equatorial_3_to_cartesian_3
  246. {
  247. inline bool apply(P1 const& p1, P2& p2) const
  248. {
  249. assert_dimension<P1, 3>();
  250. detail::spherical_equatorial_to_cartesian(
  251. get_as_radian<0>(p1), get_as_radian<1>(p1), get<2>(p1), p2);
  252. return true;
  253. }
  254. };
  255. /*!
  256. \brief Transformation strategy for 3D cartesian (x,y,z) to 2D spherical (phi,theta)
  257. \details on Unit sphere
  258. \ingroup transform
  259. \tparam P1 first point type
  260. \tparam P2 second point type
  261. \note If x,y,z point is not lying on unit sphere, transformation will return false
  262. */
  263. template <typename P1, typename P2>
  264. struct from_cartesian_3_to_spherical_polar_2
  265. {
  266. inline bool apply(P1 const& p1, P2& p2) const
  267. {
  268. assert_dimension<P1, 3>();
  269. return detail::cartesian_to_spherical2(get<0>(p1), get<1>(p1), get<2>(p1), p2);
  270. }
  271. };
  272. /*!
  273. \brief Transformation strategy for 3D cartesian (x,y,z) to 3D spherical (phi,theta,r)
  274. \ingroup transform
  275. \tparam P1 first point type
  276. \tparam P2 second point type
  277. */
  278. template <typename P1, typename P2>
  279. struct from_cartesian_3_to_spherical_polar_3
  280. {
  281. inline bool apply(P1 const& p1, P2& p2) const
  282. {
  283. assert_dimension<P1, 3>();
  284. return detail::cartesian_to_spherical3(get<0>(p1), get<1>(p1), get<2>(p1), p2);
  285. }
  286. };
  287. #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
  288. namespace services
  289. {
  290. /// Specialization for same coordinate system family, same system, same dimension, same point type, can be copied
  291. template <typename CoordSysTag, typename CoordSys, std::size_t D, typename P>
  292. struct default_strategy<CoordSysTag, CoordSysTag, CoordSys, CoordSys, D, D, P, P>
  293. {
  294. typedef copy_direct<P> type;
  295. };
  296. /// Specialization for same coordinate system family and system, same dimension, different point type, copy per coordinate
  297. template <typename CoordSysTag, typename CoordSys, std::size_t D, typename P1, typename P2>
  298. struct default_strategy<CoordSysTag, CoordSysTag, CoordSys, CoordSys, D, D, P1, P2>
  299. {
  300. typedef copy_per_coordinate<P1, P2> type;
  301. };
  302. /// Specialization to transform from degree to radian for any coordinate system / point type combination
  303. template <typename CoordSysTag, template<typename> class CoordSys, typename P1, typename P2>
  304. struct default_strategy<CoordSysTag, CoordSysTag, CoordSys<degree>, CoordSys<radian>, 2, 2, P1, P2>
  305. {
  306. typedef degree_radian_vv<P1, P2, std::multiplies> type;
  307. };
  308. /// Specialization to transform from radian to degree for any coordinate system / point type combination
  309. template <typename CoordSysTag, template<typename> class CoordSys, typename P1, typename P2>
  310. struct default_strategy<CoordSysTag, CoordSysTag, CoordSys<radian>, CoordSys<degree>, 2, 2, P1, P2>
  311. {
  312. typedef degree_radian_vv<P1, P2, std::divides> type;
  313. };
  314. /// Specialization degree->radian in 3D
  315. template <typename CoordSysTag, template<typename> class CoordSys, typename P1, typename P2>
  316. struct default_strategy<CoordSysTag, CoordSysTag, CoordSys<degree>, CoordSys<radian>, 3, 3, P1, P2>
  317. {
  318. typedef degree_radian_vv_3<P1, P2, std::multiplies> type;
  319. };
  320. /// Specialization radian->degree in 3D
  321. template <typename CoordSysTag, template<typename> class CoordSys, typename P1, typename P2>
  322. struct default_strategy<CoordSysTag, CoordSysTag, CoordSys<radian>, CoordSys<degree>, 3, 3, P1, P2>
  323. {
  324. typedef degree_radian_vv_3<P1, P2, std::divides> type;
  325. };
  326. /// Specialization to transform from unit sphere(phi,theta) to XYZ
  327. template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>
  328. struct default_strategy<spherical_polar_tag, cartesian_tag, CoordSys1, CoordSys2, 2, 3, P1, P2>
  329. {
  330. typedef from_spherical_polar_2_to_cartesian_3<P1, P2> type;
  331. };
  332. /// Specialization to transform from sphere(phi,theta,r) to XYZ
  333. template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>
  334. struct default_strategy<spherical_polar_tag, cartesian_tag, CoordSys1, CoordSys2, 3, 3, P1, P2>
  335. {
  336. typedef from_spherical_polar_3_to_cartesian_3<P1, P2> type;
  337. };
  338. template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>
  339. struct default_strategy<spherical_equatorial_tag, cartesian_tag, CoordSys1, CoordSys2, 2, 3, P1, P2>
  340. {
  341. typedef from_spherical_equatorial_2_to_cartesian_3<P1, P2> type;
  342. };
  343. template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>
  344. struct default_strategy<spherical_equatorial_tag, cartesian_tag, CoordSys1, CoordSys2, 3, 3, P1, P2>
  345. {
  346. typedef from_spherical_equatorial_3_to_cartesian_3<P1, P2> type;
  347. };
  348. /// Specialization to transform from XYZ to unit sphere(phi,theta)
  349. template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>
  350. struct default_strategy<cartesian_tag, spherical_polar_tag, CoordSys1, CoordSys2, 3, 2, P1, P2>
  351. {
  352. typedef from_cartesian_3_to_spherical_polar_2<P1, P2> type;
  353. };
  354. /// Specialization to transform from XYZ to sphere(phi,theta,r)
  355. template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>
  356. struct default_strategy<cartesian_tag, spherical_polar_tag, CoordSys1, CoordSys2, 3, 3, P1, P2>
  357. {
  358. typedef from_cartesian_3_to_spherical_polar_3<P1, P2> type;
  359. };
  360. } // namespace services
  361. #endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
  362. }} // namespace strategy::transform
  363. }} // namespace boost::geometry
  364. #endif // BOOST_GEOMETRY_STRATEGIES_STRATEGY_TRANSFORM_HPP