]>
Commit | Line | Data |
---|---|---|
92f5a8d4 | 1 | // Boost.Geometry - gis-projections (based on PROJ4) |
11fdf7f2 TL |
2 | |
3 | // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands. | |
4 | ||
1e59de90 TL |
5 | // This file was modified by Oracle on 2017, 2018, 2019, 2022. |
6 | // Modifications copyright (c) 2017-2022, Oracle and/or its affiliates. | |
7 | // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle. | |
11fdf7f2 TL |
8 | // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle. |
9 | ||
10 | // Use, modification and distribution is subject to the Boost Software License, | |
11 | // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | |
12 | // http://www.boost.org/LICENSE_1_0.txt) | |
13 | ||
14 | // This file is converted from PROJ4, http://trac.osgeo.org/proj | |
15 | // PROJ4 is originally written by Gerald Evenden (then of the USGS) | |
16 | // PROJ4 is maintained by Frank Warmerdam | |
17 | // PROJ4 is converted to Boost.Geometry by Barend Gehrels | |
18 | ||
92f5a8d4 | 19 | // Last updated version of proj: 5.0.0 |
11fdf7f2 TL |
20 | |
21 | // Original copyright notice: | |
22 | ||
23 | // Permission is hereby granted, free of charge, to any person obtaining a | |
24 | // copy of this software and associated documentation files (the "Software"), | |
25 | // to deal in the Software without restriction, including without limitation | |
26 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
27 | // and/or sell copies of the Software, and to permit persons to whom the | |
28 | // Software is furnished to do so, subject to the following conditions: | |
29 | ||
30 | // The above copyright notice and this permission notice shall be included | |
31 | // in all copies or substantial portions of the Software. | |
32 | ||
33 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
34 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
35 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
36 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
37 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
38 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
39 | // DEALINGS IN THE SOFTWARE. | |
40 | ||
92f5a8d4 TL |
41 | #ifndef BOOST_GEOMETRY_PROJECTIONS_MERC_HPP |
42 | #define BOOST_GEOMETRY_PROJECTIONS_MERC_HPP | |
11fdf7f2 TL |
43 | |
44 | #include <boost/geometry/srs/projections/impl/base_static.hpp> | |
45 | #include <boost/geometry/srs/projections/impl/base_dynamic.hpp> | |
11fdf7f2 TL |
46 | #include <boost/geometry/srs/projections/impl/factory_entry.hpp> |
47 | #include <boost/geometry/srs/projections/impl/pj_msfn.hpp> | |
92f5a8d4 | 48 | #include <boost/geometry/srs/projections/impl/pj_param.hpp> |
11fdf7f2 TL |
49 | #include <boost/geometry/srs/projections/impl/pj_phi2.hpp> |
50 | #include <boost/geometry/srs/projections/impl/pj_tsfn.hpp> | |
92f5a8d4 | 51 | #include <boost/geometry/srs/projections/impl/projects.hpp> |
11fdf7f2 | 52 | |
92f5a8d4 | 53 | #include <boost/geometry/util/math.hpp> |
11fdf7f2 | 54 | |
92f5a8d4 | 55 | namespace boost { namespace geometry |
11fdf7f2 | 56 | { |
11fdf7f2 TL |
57 | |
58 | namespace projections | |
59 | { | |
60 | #ifndef DOXYGEN_NO_DETAIL | |
61 | namespace detail { namespace merc | |
62 | { | |
63 | ||
92f5a8d4 | 64 | static const double epsilon10 = 1.e-10; |
11fdf7f2 | 65 | |
92f5a8d4 TL |
66 | template <typename T, typename Parameters> |
67 | struct base_merc_ellipsoid | |
11fdf7f2 | 68 | { |
11fdf7f2 TL |
69 | // FORWARD(e_forward) ellipsoid |
70 | // Project coordinates from geographic (lon, lat) to cartesian (x, y) | |
92f5a8d4 | 71 | inline void fwd(Parameters const& par, T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const |
11fdf7f2 | 72 | { |
92f5a8d4 | 73 | static const T half_pi = detail::half_pi<T>(); |
11fdf7f2 | 74 | |
92f5a8d4 TL |
75 | if (fabs(fabs(lp_lat) - half_pi) <= epsilon10) { |
76 | BOOST_THROW_EXCEPTION( projection_exception(error_tolerance_condition) ); | |
77 | } | |
78 | xy_x = par.k0 * lp_lon; | |
79 | xy_y = - par.k0 * log(pj_tsfn(lp_lat, sin(lp_lat), par.e)); | |
11fdf7f2 TL |
80 | } |
81 | ||
82 | // INVERSE(e_inverse) ellipsoid | |
83 | // Project coordinates from cartesian (x, y) to geographic (lon, lat) | |
92f5a8d4 | 84 | inline void inv(Parameters const& par, T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const |
11fdf7f2 | 85 | { |
92f5a8d4 TL |
86 | if ((lp_lat = pj_phi2(exp(- xy_y / par.k0), par.e)) == HUGE_VAL) { |
87 | BOOST_THROW_EXCEPTION( projection_exception(error_tolerance_condition) ); | |
88 | } | |
89 | lp_lon = xy_x / par.k0; | |
11fdf7f2 TL |
90 | } |
91 | ||
92 | static inline std::string get_name() | |
93 | { | |
94 | return "merc_ellipsoid"; | |
95 | } | |
96 | ||
97 | }; | |
98 | ||
92f5a8d4 TL |
99 | template <typename T, typename Parameters> |
100 | struct base_merc_spheroid | |
11fdf7f2 | 101 | { |
11fdf7f2 TL |
102 | // FORWARD(s_forward) spheroid |
103 | // Project coordinates from geographic (lon, lat) to cartesian (x, y) | |
92f5a8d4 | 104 | inline void fwd(Parameters const& par, T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const |
11fdf7f2 | 105 | { |
92f5a8d4 TL |
106 | static const T half_pi = detail::half_pi<T>(); |
107 | static const T fourth_pi = detail::fourth_pi<T>(); | |
108 | ||
109 | if (fabs(fabs(lp_lat) - half_pi) <= epsilon10) { | |
110 | BOOST_THROW_EXCEPTION( projection_exception(error_tolerance_condition) ); | |
111 | } | |
112 | xy_x = par.k0 * lp_lon; | |
113 | xy_y = par.k0 * log(tan(fourth_pi + .5 * lp_lat)); | |
11fdf7f2 TL |
114 | } |
115 | ||
116 | // INVERSE(s_inverse) spheroid | |
117 | // Project coordinates from cartesian (x, y) to geographic (lon, lat) | |
92f5a8d4 | 118 | inline void inv(Parameters const& par, T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const |
11fdf7f2 | 119 | { |
92f5a8d4 | 120 | static const T half_pi = detail::half_pi<T>(); |
11fdf7f2 | 121 | |
92f5a8d4 TL |
122 | lp_lat = half_pi - 2. * atan(exp(-xy_y / par.k0)); |
123 | lp_lon = xy_x / par.k0; | |
11fdf7f2 TL |
124 | } |
125 | ||
126 | static inline std::string get_name() | |
127 | { | |
128 | return "merc_spheroid"; | |
129 | } | |
130 | ||
131 | }; | |
132 | ||
133 | // Mercator | |
92f5a8d4 TL |
134 | template <typename Params, typename Parameters> |
135 | inline void setup_merc(Params const& params, Parameters& par) | |
11fdf7f2 TL |
136 | { |
137 | typedef typename Parameters::type calc_t; | |
92f5a8d4 | 138 | static const calc_t half_pi = detail::half_pi<calc_t>(); |
11fdf7f2 TL |
139 | |
140 | calc_t phits=0.0; | |
141 | int is_phits; | |
142 | ||
92f5a8d4 TL |
143 | if( (is_phits = pj_param_r<srs::spar::lat_ts>(params, "lat_ts", srs::dpar::lat_ts, phits)) ) { |
144 | phits = fabs(phits); | |
145 | if (phits >= half_pi) | |
146 | BOOST_THROW_EXCEPTION( projection_exception(error_lat_ts_larger_than_90) ); | |
11fdf7f2 | 147 | } |
92f5a8d4 | 148 | if (par.es != 0.0) { /* ellipsoid */ |
11fdf7f2 TL |
149 | if (is_phits) |
150 | par.k0 = pj_msfn(sin(phits), cos(phits), par.es); | |
151 | } else { /* sphere */ | |
152 | if (is_phits) | |
153 | par.k0 = cos(phits); | |
154 | } | |
155 | } | |
156 | ||
157 | }} // namespace detail::merc | |
158 | #endif // doxygen | |
159 | ||
160 | /*! | |
161 | \brief Mercator projection | |
162 | \ingroup projections | |
163 | \tparam Geographic latlong point type | |
164 | \tparam Cartesian xy point type | |
165 | \tparam Parameters parameter type | |
166 | \par Projection characteristics | |
167 | - Cylindrical | |
168 | - Spheroid | |
169 | - Ellipsoid | |
170 | \par Projection parameters | |
171 | - lat_ts: Latitude of true scale (degrees) | |
172 | \par Example | |
173 | \image html ex_merc.gif | |
174 | */ | |
92f5a8d4 TL |
175 | template <typename T, typename Parameters> |
176 | struct merc_ellipsoid : public detail::merc::base_merc_ellipsoid<T, Parameters> | |
11fdf7f2 | 177 | { |
92f5a8d4 TL |
178 | template <typename Params> |
179 | inline merc_ellipsoid(Params const& params, Parameters & par) | |
11fdf7f2 | 180 | { |
92f5a8d4 | 181 | detail::merc::setup_merc(params, par); |
11fdf7f2 TL |
182 | } |
183 | }; | |
184 | ||
185 | /*! | |
186 | \brief Mercator projection | |
187 | \ingroup projections | |
188 | \tparam Geographic latlong point type | |
189 | \tparam Cartesian xy point type | |
190 | \tparam Parameters parameter type | |
191 | \par Projection characteristics | |
192 | - Cylindrical | |
193 | - Spheroid | |
194 | - Ellipsoid | |
195 | \par Projection parameters | |
196 | - lat_ts: Latitude of true scale (degrees) | |
197 | \par Example | |
198 | \image html ex_merc.gif | |
199 | */ | |
92f5a8d4 TL |
200 | template <typename T, typename Parameters> |
201 | struct merc_spheroid : public detail::merc::base_merc_spheroid<T, Parameters> | |
11fdf7f2 | 202 | { |
92f5a8d4 TL |
203 | template <typename Params> |
204 | inline merc_spheroid(Params const& params, Parameters & par) | |
11fdf7f2 | 205 | { |
92f5a8d4 | 206 | detail::merc::setup_merc(params, par); |
11fdf7f2 TL |
207 | } |
208 | }; | |
209 | ||
1e59de90 TL |
210 | /*! |
211 | \brief Web Mercator projection | |
212 | \ingroup projections | |
213 | \tparam Geographic latlong point type | |
214 | \tparam Cartesian xy point type | |
215 | \tparam Parameters parameter type | |
216 | \par Projection characteristics | |
217 | - Cylindrical | |
218 | - Spheroid | |
219 | - Ellipsoid | |
220 | */ | |
221 | template <typename T, typename Parameters> | |
222 | struct webmerc_spheroid : public detail::merc::base_merc_spheroid<T, Parameters> | |
223 | { | |
224 | template <typename Params> | |
225 | inline webmerc_spheroid(Params const&, Parameters & par) | |
226 | { | |
227 | par.k0 = 1; | |
228 | } | |
229 | }; | |
230 | ||
11fdf7f2 TL |
231 | #ifndef DOXYGEN_NO_DETAIL |
232 | namespace detail | |
233 | { | |
234 | ||
235 | // Static projection | |
1e59de90 TL |
236 | BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI2(srs::spar::proj_merc, merc_spheroid, |
237 | merc_ellipsoid) | |
238 | BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_webmerc, | |
239 | webmerc_spheroid) | |
11fdf7f2 TL |
240 | |
241 | // Factory entry(s) | |
1e59de90 TL |
242 | BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI2(merc_entry, merc_spheroid, |
243 | merc_ellipsoid) | |
244 | BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(webmerc_entry, webmerc_spheroid) | |
245 | ||
92f5a8d4 | 246 | BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(merc_init) |
11fdf7f2 | 247 | { |
92f5a8d4 | 248 | BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(merc, merc_entry) |
1e59de90 | 249 | BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(webmerc, webmerc_entry) |
11fdf7f2 TL |
250 | } |
251 | ||
252 | } // namespace detail | |
253 | #endif // doxygen | |
254 | ||
255 | } // namespace projections | |
256 | ||
257 | }} // namespace boost::geometry | |
258 | ||
259 | #endif // BOOST_GEOMETRY_PROJECTIONS_MERC_HPP |