• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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