1 // Boost.Geometry 2 3 // Copyright (c) 2017-2019, Oracle and/or its affiliates. 4 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle 5 6 // Use, modification and distribution is subject to the Boost Software License, 7 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at 8 // http://www.boost.org/LICENSE_1_0.txt) 9 10 #ifndef BOOST_GEOMETRY_TEST_SRS_PROJ4_HPP 11 #define BOOST_GEOMETRY_TEST_SRS_PROJ4_HPP 12 13 #include <string> 14 15 #include <boost/geometry/core/access.hpp> 16 #include <boost/geometry/core/radian_access.hpp> 17 18 #if defined(TEST_WITH_PROJ6) 19 #define TEST_WITH_PROJ5 20 #endif 21 22 #if defined(TEST_WITH_PROJ5) 23 #define TEST_WITH_PROJ4 24 25 #include <proj.h> 26 27 #endif 28 29 #if defined(TEST_WITH_PROJ4) 30 #define ACCEPT_USE_OF_DEPRECATED_PROJ_API_H 31 32 #include <proj_api.h> 33 34 struct pj_ptr 35 { pj_ptrpj_ptr36 explicit pj_ptr(projPJ ptr = NULL) 37 : m_ptr(ptr) 38 {} 39 40 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES pj_ptrpj_ptr41 pj_ptr(pj_ptr && other) 42 : m_ptr(other.m_ptr) 43 { 44 other.m_ptr = NULL; 45 } 46 operator =pj_ptr47 pj_ptr & operator=(pj_ptr && other) 48 { 49 if (m_ptr) 50 pj_free(m_ptr); 51 m_ptr = other.m_ptr; 52 other.m_ptr = NULL; 53 return *this; 54 } 55 #endif 56 getpj_ptr57 projPJ get() const 58 { 59 return m_ptr; 60 } 61 ~pj_ptrpj_ptr62 ~pj_ptr() 63 { 64 if (m_ptr) 65 pj_free(m_ptr); 66 } 67 68 private: 69 pj_ptr(pj_ptr const&); 70 pj_ptr & operator=(pj_ptr const&); 71 72 projPJ m_ptr; 73 }; 74 /* 75 struct pj_projection 76 { 77 pj_projection(std::string const& prj) 78 : m_ptr(pj_init_plus(prj.c_str())) 79 {} 80 81 template <typename In, typename Out> 82 void forward(In const& in, Out & out) const 83 { 84 double x = boost::geometry::get_as_radian<0>(in); 85 double y = boost::geometry::get_as_radian<1>(in); 86 87 projUV p1; 88 projUV p2; 89 90 p1.u = x; 91 p1.v = y; 92 93 p2 = pj_fwd(p1, m_ptr.get()); 94 95 boost::geometry::set_from_radian<0>(out, p2.u); 96 boost::geometry::set_from_radian<1>(out, p2.v); 97 } 98 99 template <typename In, typename Out> 100 void inverse(In const& in, Out & out) const 101 { 102 double lon = boost::geometry::get_as_radian<0>(in); 103 double lat = boost::geometry::get_as_radian<1>(in); 104 105 projUV p1; 106 projUV p2; 107 108 p1.u = lon; 109 p1.v = lat; 110 111 p2 = pj_inv(p1, m_ptr.get()); 112 113 boost::geometry::set_from_radian<0>(out, p2.u); 114 boost::geometry::set_from_radian<1>(out, p2.v); 115 } 116 117 private: 118 pj_ptr m_ptr; 119 };*/ 120 121 struct pj_transformation 122 { pj_transformationpj_transformation123 pj_transformation(std::string const& from, std::string const& to) 124 : m_from(pj_init_plus(from.c_str())) 125 , m_to(pj_init_plus(to.c_str())) 126 {} 127 forwardpj_transformation128 void forward(std::vector<double> in_x, 129 std::vector<double> in_y, 130 std::vector<double> & out_x, 131 std::vector<double> & out_y) const 132 { 133 assert(in_x.size() == in_y.size()); 134 pj_transform(m_from.get(), m_to.get(), (long)in_x.size(), 1, &in_x[0], &in_y[0], NULL); 135 out_x = std::move(in_x); 136 out_y = std::move(in_y); 137 } 138 forwardpj_transformation139 void forward(std::vector<double> in_xy, 140 std::vector<double> & out_xy) const 141 { 142 assert(in_xy.size() % 2 == 0); 143 pj_transform(m_from.get(), m_to.get(), (long)in_xy.size() / 2, 2, &in_xy[0], &in_xy[1], NULL); 144 out_xy = std::move(in_xy); 145 } 146 forwardpj_transformation147 void forward(std::vector<std::vector<double> > const& in_xy, 148 std::vector<std::vector<double> > & out_xy) const 149 { 150 out_xy.resize(in_xy.size()); 151 for (size_t i = 0 ; i < in_xy.size(); ++i) 152 forward(in_xy[i], out_xy[i]); 153 } 154 155 template <typename In, typename Out> forwardpj_transformation156 void forward(In const& in, Out & out, 157 typename boost::enable_if_c 158 < 159 boost::is_same 160 < 161 typename boost::geometry::tag<In>::type, 162 boost::geometry::point_tag 163 >::value 164 >::type* dummy = 0) const 165 { 166 transform_point(in, out, m_from, m_to); 167 } 168 169 template <typename In, typename Out> inversepj_transformation170 void inverse(In const& in, Out & out, 171 typename boost::enable_if_c 172 < 173 boost::is_same 174 < 175 typename boost::geometry::tag<In>::type, 176 boost::geometry::point_tag 177 >::value 178 >::type* dummy = 0) const 179 { 180 transform_point(in, out, m_to, m_from); 181 } 182 183 private: 184 template <typename In, typename Out> transform_pointpj_transformation185 static void transform_point(In const& in, Out & out, 186 pj_ptr const& from, pj_ptr const& to) 187 { 188 double x = boost::geometry::get_as_radian<0>(in); 189 double y = boost::geometry::get_as_radian<1>(in); 190 191 pj_transform(from.get(), to.get(), 1, 0, &x, &y, NULL); 192 193 boost::geometry::set_from_radian<0>(out, x); 194 boost::geometry::set_from_radian<1>(out, y); 195 } 196 197 pj_ptr m_from; 198 pj_ptr m_to; 199 }; 200 201 #endif // TEST_WITH_PROJ4 202 203 #if defined(TEST_WITH_PROJ5) 204 205 struct proj5_ptr 206 { proj5_ptrproj5_ptr207 explicit proj5_ptr(PJ *ptr = NULL) 208 : m_ptr(ptr) 209 {} 210 211 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES proj5_ptrproj5_ptr212 proj5_ptr(proj5_ptr && other) 213 : m_ptr(other.m_ptr) 214 { 215 other.m_ptr = NULL; 216 } 217 operator =proj5_ptr218 proj5_ptr & operator=(proj5_ptr && other) 219 { 220 if (m_ptr) 221 proj_destroy(m_ptr); 222 m_ptr = other.m_ptr; 223 other.m_ptr = NULL; 224 return *this; 225 } 226 #endif 227 getproj5_ptr228 PJ *get() const 229 { 230 return m_ptr; 231 } 232 ~proj5_ptrproj5_ptr233 ~proj5_ptr() 234 { 235 if (m_ptr) 236 proj_destroy(m_ptr); 237 } 238 239 private: 240 proj5_ptr(proj5_ptr const&); 241 proj5_ptr & operator=(proj5_ptr const&); 242 243 PJ *m_ptr; 244 }; 245 246 struct proj5_transformation 247 { proj5_transformationproj5_transformation248 proj5_transformation(std::string const& to) 249 : m_proj(proj_create(PJ_DEFAULT_CTX, to.c_str())) 250 {} 251 forwardproj5_transformation252 void forward(std::vector<PJ_COORD> in, 253 std::vector<PJ_COORD> & out) const 254 { 255 proj_trans_array(m_proj.get(), PJ_FWD, in.size(), &in[0]); 256 out = std::move(in); 257 } 258 259 template <typename In, typename Out> forwardproj5_transformation260 void forward(In const& in, Out & out, 261 typename boost::enable_if_c 262 < 263 boost::is_same 264 < 265 typename boost::geometry::tag<In>::type, 266 boost::geometry::point_tag 267 >::value 268 >::type* dummy = 0) const 269 { 270 PJ_COORD c; 271 c.lp.lam = boost::geometry::get_as_radian<0>(in); 272 c.lp.phi = boost::geometry::get_as_radian<1>(in); 273 274 c = proj_trans(m_proj.get(), PJ_FWD, c); 275 276 boost::geometry::set_from_radian<0>(out, c.xy.x); 277 boost::geometry::set_from_radian<1>(out, c.xy.y); 278 } 279 280 private: 281 proj5_ptr m_proj; 282 }; 283 284 #endif // TEST_WITH_PROJ5 285 286 #if defined(TEST_WITH_PROJ6) 287 288 struct proj6_transformation 289 { proj6_transformationproj6_transformation290 proj6_transformation(std::string const& from, std::string const& to) 291 : m_proj(proj_create_crs_to_crs(PJ_DEFAULT_CTX, from.c_str(), to.c_str(), NULL)) 292 { 293 //proj_normalize_for_visualization(0, m_proj.get()); 294 } 295 forwardproj6_transformation296 void forward(std::vector<PJ_COORD> in, 297 std::vector<PJ_COORD> & out) const 298 { 299 proj_trans_array(m_proj.get(), PJ_FWD, in.size(), &in[0]); 300 out = std::move(in); 301 } 302 303 template <typename In, typename Out> forwardproj6_transformation304 void forward(In const& in, Out & out, 305 typename boost::enable_if_c 306 < 307 boost::is_same 308 < 309 typename boost::geometry::tag<In>::type, 310 boost::geometry::point_tag 311 >::value 312 >::type* dummy = 0) const 313 { 314 PJ_COORD c; 315 c.lp.lam = boost::geometry::get_as_radian<0>(in); 316 c.lp.phi = boost::geometry::get_as_radian<1>(in); 317 318 c = proj_trans(m_proj.get(), PJ_FWD, c); 319 320 boost::geometry::set_from_radian<0>(out, c.xy.x); 321 boost::geometry::set_from_radian<1>(out, c.xy.y); 322 } 323 324 private: 325 proj5_ptr m_proj; 326 }; 327 328 #endif // TEST_WITH_PROJ6 329 330 #endif // BOOST_GEOMETRY_TEST_SRS_PROJ4_HPP 331