par4.hpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504
  1. // Boost.Geometry
  2. // Copyright (c) 2017-2018, Oracle and/or its affiliates.
  3. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  4. // Use, modification and distribution is subject to the Boost Software License,
  5. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. #ifndef BOOST_GEOMETRY_SRS_PROJECTIONS_PAR4_HPP
  8. #define BOOST_GEOMETRY_SRS_PROJECTIONS_PAR4_HPP
  9. #include <boost/geometry/core/tag.hpp>
  10. #include <boost/geometry/core/tags.hpp>
  11. #include <boost/geometry/srs/sphere.hpp>
  12. #include <boost/geometry/srs/spheroid.hpp>
  13. #include <boost/mpl/assert.hpp>
  14. #include <boost/mpl/if.hpp>
  15. #include <boost/tuple/tuple.hpp>
  16. #include <boost/type_traits/integral_constant.hpp>
  17. #include <boost/type_traits/is_same.hpp>
  18. #include <boost/type_traits/is_void.hpp>
  19. namespace boost { namespace geometry { namespace srs { namespace par4
  20. {
  21. // proj
  22. // defined in projections' implementation files
  23. // ellps
  24. struct MERIT {};
  25. struct SGS85 {};
  26. struct GRS80 {};
  27. struct IAU76 {};
  28. struct airy {};
  29. struct APL4_9 {};
  30. struct NWL9D {};
  31. struct mod_airy {};
  32. struct andrae {};
  33. struct aust_SA {};
  34. struct GRS67 {};
  35. struct bessel {};
  36. struct bess_nam {};
  37. struct clrk66 {};
  38. struct clrk80 {};
  39. struct clrk80ign {};
  40. struct CPM {};
  41. struct delmbr {};
  42. struct engelis {};
  43. struct evrst30 {};
  44. struct evrst48 {};
  45. struct evrst56 {};
  46. struct evrst69 {};
  47. struct evrstSS {};
  48. struct fschr60 {};
  49. struct fschr60m {};
  50. struct fschr68 {};
  51. struct helmert {};
  52. struct hough {};
  53. struct intl {};
  54. struct krass {};
  55. struct kaula {};
  56. struct lerch {};
  57. struct mprts {};
  58. struct new_intl {};
  59. struct plessis {};
  60. struct SEasia {};
  61. struct walbeck {};
  62. struct WGS60 {};
  63. struct WGS66 {};
  64. struct WGS72 {};
  65. struct WGS84 {};
  66. struct sphere {};
  67. // datum
  68. //struct WGS84 {}; // already defined above
  69. struct GGRS87 {};
  70. struct NAD83 {};
  71. struct NAD27 {};
  72. struct potsdam {};
  73. struct carthage {};
  74. struct hermannskogel {};
  75. struct ire65 {};
  76. struct nzgd49 {};
  77. struct OSGB36 {};
  78. template <typename P>
  79. struct proj
  80. {
  81. typedef P type;
  82. };
  83. #ifndef DOXYGEN_NO_DETAIL
  84. namespace detail
  85. {
  86. template
  87. <
  88. typename E,
  89. typename Tag = typename geometry::tag<E>::type
  90. >
  91. struct ellps_impl
  92. : private E // empty base optimization
  93. {
  94. typedef E type;
  95. ellps_impl() : E() {}
  96. explicit ellps_impl(E const& e) : E(e) {}
  97. E const& model() const { return *this; }
  98. };
  99. template <typename E>
  100. struct ellps_impl<E, void>
  101. {
  102. typedef E type;
  103. };
  104. } // namespace detail
  105. #endif // DOXYGEN_NO_DETAIL
  106. template<typename E>
  107. struct ellps
  108. : par4::detail::ellps_impl<E>
  109. {
  110. ellps() {}
  111. explicit ellps(E const& e)
  112. : par4::detail::ellps_impl<E>(e)
  113. {}
  114. };
  115. template <typename D>
  116. struct datum
  117. {
  118. typedef D type;
  119. };
  120. template <typename P>
  121. struct o_proj
  122. {
  123. typedef P type;
  124. };
  125. struct guam {};
  126. #ifndef DOXYGEN_NO_DETAIL
  127. namespace detail
  128. {
  129. inline double b_from_a_rf(double a, double rf)
  130. {
  131. return a * (1.0 - 1.0 / rf);
  132. }
  133. template
  134. <
  135. typename Ellps,
  136. typename Tag = typename geometry::tag<typename Ellps::type>::type
  137. >
  138. struct ellps_traits
  139. {
  140. typedef typename Ellps::type model_type;
  141. static model_type model(Ellps const& e) { return e.model(); }
  142. };
  143. #define BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_ELLPS_A_B(NAME, A, B) \
  144. template <> \
  145. struct ellps_traits<ellps<par4::NAME>, void> \
  146. { \
  147. typedef srs::spheroid<double> model_type; \
  148. static model_type model(ellps<par4::NAME> const&) { return model_type(A, B); } \
  149. };
  150. #define BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_ELLPS_A_RF(NAME, A, RF) \
  151. template <> \
  152. struct ellps_traits<ellps<par4::NAME>, void> \
  153. { \
  154. typedef srs::spheroid<double> model_type; \
  155. static model_type model(ellps<par4::NAME> const&) { return model_type(A, b_from_a_rf(A, RF)); } \
  156. };
  157. #define BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_SPHERE(NAME, R) \
  158. template <> \
  159. struct ellps_traits<ellps<par4::NAME>, void> \
  160. { \
  161. typedef srs::sphere<double> model_type; \
  162. static model_type model(ellps<par4::NAME> const&) { return model_type(R); } \
  163. };
  164. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_ELLPS_A_RF(MERIT, 6378137.0, 298.257)
  165. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_ELLPS_A_RF(SGS85, 6378136.0, 298.257)
  166. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_ELLPS_A_RF(GRS80, 6378137.0, 298.257222101)
  167. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_ELLPS_A_RF(IAU76, 6378140.0, 298.257)
  168. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_ELLPS_A_B (airy, 6377563.396, 6356256.910)
  169. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_ELLPS_A_RF(APL4_9, 6378137.0, 298.25)
  170. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_ELLPS_A_RF(NWL9D, 6378145.0, 298.25)
  171. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_ELLPS_A_B (mod_airy, 6377340.189, 6356034.446)
  172. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_ELLPS_A_RF(andrae, 6377104.43, 300.0)
  173. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_ELLPS_A_RF(aust_SA, 6378160.0, 298.25)
  174. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_ELLPS_A_RF(GRS67, 6378160.0, 298.2471674270)
  175. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_ELLPS_A_RF(bessel, 6377397.155, 299.1528128)
  176. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_ELLPS_A_RF(bess_nam, 6377483.865, 299.1528128)
  177. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_ELLPS_A_B (clrk66, 6378206.4, 6356583.8)
  178. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_ELLPS_A_RF(clrk80, 6378249.145, 293.4663)
  179. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_ELLPS_A_RF(clrk80ign, 6378249.2, 293.4660212936269)
  180. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_ELLPS_A_RF(CPM, 6375738.7, 334.29)
  181. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_ELLPS_A_RF(delmbr, 6376428.0, 311.5)
  182. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_ELLPS_A_RF(engelis, 6378136.05, 298.2566)
  183. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_ELLPS_A_RF(evrst30, 6377276.345, 300.8017)
  184. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_ELLPS_A_RF(evrst48, 6377304.063, 300.8017)
  185. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_ELLPS_A_RF(evrst56, 6377301.243, 300.8017)
  186. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_ELLPS_A_RF(evrst69, 6377295.664, 300.8017)
  187. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_ELLPS_A_RF(evrstSS, 6377298.556, 300.8017)
  188. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_ELLPS_A_RF(fschr60, 6378166.0, 298.3)
  189. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_ELLPS_A_RF(fschr60m, 6378155.0, 298.3)
  190. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_ELLPS_A_RF(fschr68, 6378150.0, 298.3)
  191. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_ELLPS_A_RF(helmert, 6378200.0, 298.3)
  192. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_ELLPS_A_RF(hough, 6378270.0, 297.0)
  193. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_ELLPS_A_RF(intl, 6378388.0, 297.0)
  194. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_ELLPS_A_RF(krass, 6378245.0, 298.3)
  195. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_ELLPS_A_RF(kaula, 6378163.0, 298.24)
  196. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_ELLPS_A_RF(lerch, 6378139.0, 298.257)
  197. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_ELLPS_A_RF(mprts, 6397300.0, 191.0)
  198. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_ELLPS_A_B (new_intl, 6378157.5, 6356772.2)
  199. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_ELLPS_A_B (plessis, 6376523.0, 6355863.0)
  200. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_ELLPS_A_B (SEasia, 6378155.0, 6356773.3205)
  201. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_ELLPS_A_B (walbeck, 6376896.0, 6355834.8467)
  202. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_ELLPS_A_RF(WGS60, 6378165.0, 298.3)
  203. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_ELLPS_A_RF(WGS66, 6378145.0, 298.25)
  204. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_ELLPS_A_RF(WGS72, 6378135.0, 298.26)
  205. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_ELLPS_A_RF(WGS84, 6378137.0, 298.257223563)
  206. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_SPHERE (sphere, 6370997.0)
  207. template <typename D>
  208. struct datum_traits
  209. {
  210. typedef void ellps_type;
  211. static std::string id() { return ""; }
  212. static std::string def_n() { return ""; }
  213. static std::string def_v() { return ""; }
  214. };
  215. #define BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_DATUM(NAME, ID, ELLPS, DEF_N, DEF_V) \
  216. template <> \
  217. struct datum_traits< datum<par4::NAME> > \
  218. { \
  219. typedef par4::ellps<par4::ELLPS> ellps_type; \
  220. static std::string id() { return ID; } \
  221. static std::string def_n() { return DEF_N; } \
  222. static std::string def_v() { return DEF_V; } \
  223. };
  224. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_DATUM(WGS84, "WGS84", WGS84, "towgs84", "0,0,0")
  225. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_DATUM(GGRS87, "GGRS87", GRS80, "towgs84", "-199.87,74.79,246.62")
  226. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_DATUM(NAD83, "NAD83", GRS80, "towgs84", "0,0,0")
  227. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_DATUM(NAD27, "NAD27", clrk66, "nadgrids", "@conus,@alaska,@ntv2_0.gsb,@ntv1_can.dat")
  228. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_DATUM(potsdam, "potsdam", bessel, "towgs84", "598.1,73.7,418.2,0.202,0.045,-2.455,6.7")
  229. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_DATUM(carthage, "carthage", clrk80ign, "towgs84", "-263.0,6.0,431.0")
  230. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_DATUM(hermannskogel, "hermannskogel", bessel, "towgs84", "577.326,90.129,463.919,5.137,1.474,5.297,2.4232")
  231. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_DATUM(ire65, "ire65", mod_airy, "towgs84", "482.530,-130.596,564.557,-1.042,-0.214,-0.631,8.15")
  232. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_DATUM(nzgd49, "nzgd49", intl, "towgs84", "59.47,-5.04,187.44,0.47,-0.1,1.024,-4.5993")
  233. BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_DATUM(OSGB36, "OSGB36", airy, "towgs84", "446.448,-125.157,542.060,0.1502,0.2470,0.8421,-20.4894")
  234. template
  235. <
  236. typename Tuple,
  237. template <typename> class IsSamePred,
  238. int I = 0,
  239. int N = boost::tuples::length<Tuple>::value
  240. >
  241. struct tuples_find_index_if
  242. : boost::mpl::if_c
  243. <
  244. IsSamePred<typename boost::tuples::element<I, Tuple>::type>::value,
  245. boost::integral_constant<int, I>,
  246. typename tuples_find_index_if<Tuple, IsSamePred, I+1, N>::type
  247. >::type
  248. {};
  249. template
  250. <
  251. typename Tuple,
  252. template <typename> class IsSamePred,
  253. int N
  254. >
  255. struct tuples_find_index_if<Tuple, IsSamePred, N, N>
  256. : boost::integral_constant<int, N>
  257. {};
  258. template
  259. <
  260. typename Tuple,
  261. template <typename> class IsSamePred,
  262. int I = tuples_find_index_if<Tuple, IsSamePred>::value,
  263. int N = boost::tuples::length<Tuple>::value
  264. >
  265. struct tuples_find_if
  266. : boost::tuples::element<I, Tuple>
  267. {};
  268. template
  269. <
  270. typename Tuple,
  271. template <typename> class IsSamePred,
  272. int N
  273. >
  274. struct tuples_find_if<Tuple, IsSamePred, N, N>
  275. {
  276. typedef void type;
  277. };
  278. /*template <typename Param>
  279. struct is_param
  280. {
  281. template <typename T, int D = 0>
  282. struct is_same_impl : boost::false_type {};
  283. template <int D>
  284. struct is_same_impl<Param, D> : boost::true_type {};
  285. template <typename T>
  286. struct is_same : is_same_impl<T> {};
  287. };
  288. template <template <typename> class Param>
  289. struct is_param_t
  290. {
  291. template <typename T>
  292. struct is_same : boost::false_type {};
  293. template <typename T>
  294. struct is_same<Param<T> > : boost::true_type {};
  295. };*/
  296. // NOTE: The following metafunctions are implemented one for each parameter
  297. // because mingw-gcc-4.1.2 is unable to compile a solution based on template
  298. // template parameter and member struct template partial specialization
  299. // (see above).
  300. /*template <typename T>
  301. struct is_proj : boost::false_type {};
  302. template <typename T>
  303. struct is_proj<proj<T> > : boost::true_type {};
  304. template <typename T>
  305. struct is_ellps : boost::false_type {};
  306. template <typename T>
  307. struct is_ellps<ellps<T> > : boost::true_type {};
  308. template <typename T>
  309. struct is_datum : boost::false_type {};
  310. template <typename T>
  311. struct is_datum<datum<T> > : boost::true_type {};
  312. template <typename T>
  313. struct is_o_proj : boost::false_type {};
  314. template <typename T>
  315. struct is_o_proj<o_proj<T> > : boost::true_type {};
  316. template <typename T>
  317. struct is_guam : boost::false_type {};
  318. template <>
  319. struct is_guam<guam> : boost::true_type {};*/
  320. // NOTE: The following implementation seems to work as well.
  321. // TEST
  322. template <typename T, template <typename> class Param>
  323. struct is_same_t : boost::false_type {};
  324. template <typename T, template <typename> class Param>
  325. struct is_same_t<Param<T>, Param> : boost::true_type {};
  326. template <typename Param>
  327. struct is_param
  328. {
  329. template <typename T>
  330. struct pred : boost::is_same<T, Param> {};
  331. };
  332. template <template <typename> class Param>
  333. struct is_param_t
  334. {
  335. template <typename T>
  336. struct pred : is_same_t<T, Param> {};
  337. };
  338. // pick proj static name
  339. template <typename Tuple>
  340. struct pick_proj_tag
  341. {
  342. typedef typename tuples_find_if
  343. <
  344. Tuple,
  345. // is_proj
  346. is_param_t<proj>::pred
  347. >::type proj_type;
  348. static const bool is_non_void = ! boost::is_void<proj_type>::value;
  349. BOOST_MPL_ASSERT_MSG((is_non_void), PROJECTION_NOT_NAMED, (Tuple));
  350. typedef typename proj_type::type type;
  351. };
  352. template <typename Ellps, typename Datum, int EllpsIndex>
  353. struct pick_ellps_impl
  354. {
  355. typedef Ellps type;
  356. typedef typename ellps_traits<Ellps>::model_type model_type;
  357. template <typename Tuple>
  358. static model_type model(Tuple const& tup)
  359. {
  360. return ellps_traits<Ellps>::model(boost::get<EllpsIndex>(tup));
  361. }
  362. };
  363. template <typename Ellps, int EllpsIndex>
  364. struct pick_ellps_impl<Ellps, void, EllpsIndex>
  365. {
  366. typedef Ellps type;
  367. typedef typename ellps_traits<Ellps>::model_type model_type;
  368. template <typename Tuple>
  369. static model_type model(Tuple const& tup)
  370. {
  371. return ellps_traits<Ellps>::model(boost::get<EllpsIndex>(tup));
  372. }
  373. };
  374. template <typename Datum, int EllpsIndex>
  375. struct pick_ellps_impl<void, Datum, EllpsIndex>
  376. {
  377. typedef typename datum_traits<Datum>::ellps_type type;
  378. static const bool is_datum_known = ! boost::is_void<type>::value;
  379. BOOST_MPL_ASSERT_MSG((is_datum_known), UNKNOWN_DATUM, (types<Datum>));
  380. typedef typename ellps_traits<type>::model_type model_type;
  381. template <typename Tuple>
  382. static model_type model(Tuple const& )
  383. {
  384. return ellps_traits<type>::model(type());
  385. }
  386. };
  387. template <int EllpsIndex>
  388. struct pick_ellps_impl<void, void, EllpsIndex>
  389. {
  390. // default ellipsoid
  391. typedef ellps<WGS84> type;
  392. typedef typename ellps_traits<type>::model_type model_type;
  393. template <typename Tuple>
  394. static model_type model(Tuple const& )
  395. {
  396. return ellps_traits<type>::model(type());
  397. }
  398. };
  399. // Pick spheroid/sphere model from ellps or datum
  400. // mimic pj_init() calling pj_datum_set() and pj_ell_set()
  401. template <typename Tuple>
  402. struct pick_ellps
  403. : pick_ellps_impl
  404. <
  405. typename tuples_find_if<Tuple, /*is_ellps*/is_param_t<ellps>::pred>::type,
  406. typename tuples_find_if<Tuple, /*is_datum*/is_param_t<datum>::pred>::type,
  407. tuples_find_index_if<Tuple, /*is_ellps*/is_param_t<ellps>::pred>::value
  408. >
  409. {};
  410. template <typename Tuple>
  411. struct pick_o_proj_tag
  412. {
  413. typedef typename tuples_find_if
  414. <
  415. Tuple,
  416. //is_o_proj
  417. is_param_t<o_proj>::pred
  418. >::type proj_type;
  419. static const bool is_non_void = ! boost::is_void<proj_type>::value;
  420. BOOST_MPL_ASSERT_MSG((is_non_void), NO_O_PROJ_PARAMETER, (Tuple));
  421. typedef typename proj_type::type type;
  422. };
  423. } // namespace detail
  424. #endif // DOXYGEN_NO_DETAIL
  425. }}}} // namespace boost::geometry::srs::par4
  426. #endif // BOOST_GEOMETRY_SRS_PROJECTIONS_PAR4_HPP