File indexing completed on 2025-01-18 09:35:45
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040 #ifndef BOOST_GEOMETRY_PROJECTIONS_ORTHO_HPP
0041 #define BOOST_GEOMETRY_PROJECTIONS_ORTHO_HPP
0042
0043 #include <boost/config.hpp>
0044 #include <boost/geometry/util/math.hpp>
0045 #include <boost/math/special_functions/hypot.hpp>
0046
0047 #include <boost/geometry/srs/projections/impl/base_static.hpp>
0048 #include <boost/geometry/srs/projections/impl/base_dynamic.hpp>
0049 #include <boost/geometry/srs/projections/impl/projects.hpp>
0050 #include <boost/geometry/srs/projections/impl/factory_entry.hpp>
0051
0052 namespace boost { namespace geometry
0053 {
0054
0055 namespace projections
0056 {
0057 #ifndef DOXYGEN_NO_DETAIL
0058 namespace detail { namespace ortho
0059 {
0060
0061 enum mode_type {
0062 n_pole = 0,
0063 s_pole = 1,
0064 equit = 2,
0065 obliq = 3
0066 };
0067
0068 template <typename T>
0069 struct par_ortho
0070 {
0071 T sinph0;
0072 T cosph0;
0073 mode_type mode;
0074 };
0075
0076 static const double epsilon10 = 1.e-10;
0077
0078 template <typename T, typename Parameters>
0079 struct base_ortho_spheroid
0080 {
0081 par_ortho<T> m_proj_parm;
0082
0083
0084
0085 inline void fwd(Parameters const& par, T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const
0086 {
0087 static const T half_pi = detail::half_pi<T>();
0088
0089 T coslam, cosphi, sinphi;
0090
0091 cosphi = cos(lp_lat);
0092 coslam = cos(lp_lon);
0093 switch (this->m_proj_parm.mode) {
0094 case equit:
0095 if (cosphi * coslam < - epsilon10) {
0096 BOOST_THROW_EXCEPTION( projection_exception(error_tolerance_condition) );
0097 }
0098 xy_y = sin(lp_lat);
0099 break;
0100 case obliq:
0101 if (this->m_proj_parm.sinph0 * (sinphi = sin(lp_lat)) +
0102 this->m_proj_parm.cosph0 * cosphi * coslam < - epsilon10) {
0103 BOOST_THROW_EXCEPTION( projection_exception(error_tolerance_condition) );
0104 }
0105 xy_y = this->m_proj_parm.cosph0 * sinphi - this->m_proj_parm.sinph0 * cosphi * coslam;
0106 break;
0107 case n_pole:
0108 coslam = - coslam;
0109 BOOST_FALLTHROUGH;
0110 case s_pole:
0111 if (fabs(lp_lat - par.phi0) - epsilon10 > half_pi) {
0112 BOOST_THROW_EXCEPTION( projection_exception(error_tolerance_condition) );
0113 }
0114 xy_y = cosphi * coslam;
0115 break;
0116 }
0117 xy_x = cosphi * sin(lp_lon);
0118 }
0119
0120
0121
0122 inline void inv(Parameters const& par, T xy_x, T xy_y, T& lp_lon, T& lp_lat) const
0123 {
0124 static const T half_pi = detail::half_pi<T>();
0125
0126 T rh, cosc, sinc;
0127
0128 if ((sinc = (rh = boost::math::hypot(xy_x, xy_y))) > 1.) {
0129 if ((sinc - 1.) > epsilon10) {
0130 BOOST_THROW_EXCEPTION( projection_exception(error_tolerance_condition) );
0131 }
0132 sinc = 1.;
0133 }
0134 cosc = sqrt(1. - sinc * sinc);
0135 if (fabs(rh) <= epsilon10) {
0136 lp_lat = par.phi0;
0137 lp_lon = 0.0;
0138 } else {
0139 switch (this->m_proj_parm.mode) {
0140 case n_pole:
0141 xy_y = -xy_y;
0142 lp_lat = acos(sinc);
0143 break;
0144 case s_pole:
0145 lp_lat = - acos(sinc);
0146 break;
0147 case equit:
0148 lp_lat = xy_y * sinc / rh;
0149 xy_x *= sinc;
0150 xy_y = cosc * rh;
0151 goto sinchk;
0152 case obliq:
0153 lp_lat = cosc * this->m_proj_parm.sinph0 + xy_y * sinc * this->m_proj_parm.cosph0 /rh;
0154 xy_y = (cosc - this->m_proj_parm.sinph0 * lp_lat) * rh;
0155 xy_x *= sinc * this->m_proj_parm.cosph0;
0156 sinchk:
0157 if (fabs(lp_lat) >= 1.)
0158 lp_lat = lp_lat < 0. ? -half_pi : half_pi;
0159 else
0160 lp_lat = asin(lp_lat);
0161 break;
0162 }
0163 lp_lon = (xy_y == 0. && (this->m_proj_parm.mode == obliq || this->m_proj_parm.mode == equit))
0164 ? (xy_x == 0. ? 0. : xy_x < 0. ? -half_pi : half_pi)
0165 : atan2(xy_x, xy_y);
0166 }
0167 }
0168
0169 static inline std::string get_name()
0170 {
0171 return "ortho_spheroid";
0172 }
0173
0174 };
0175
0176
0177 template <typename Parameters, typename T>
0178 inline void setup_ortho(Parameters& par, par_ortho<T>& proj_parm)
0179 {
0180 if (fabs(fabs(par.phi0) - geometry::math::half_pi<T>()) <= epsilon10)
0181 proj_parm.mode = par.phi0 < 0. ? s_pole : n_pole;
0182 else if (fabs(par.phi0) > epsilon10) {
0183 proj_parm.mode = obliq;
0184 proj_parm.sinph0 = sin(par.phi0);
0185 proj_parm.cosph0 = cos(par.phi0);
0186 } else
0187 proj_parm.mode = equit;
0188 par.es = 0.;
0189 }
0190
0191 }}
0192 #endif
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206 template <typename T, typename Parameters>
0207 struct ortho_spheroid : public detail::ortho::base_ortho_spheroid<T, Parameters>
0208 {
0209 template <typename Params>
0210 inline ortho_spheroid(Params const& , Parameters & par)
0211 {
0212 detail::ortho::setup_ortho(par, this->m_proj_parm);
0213 }
0214 };
0215
0216 #ifndef DOXYGEN_NO_DETAIL
0217 namespace detail
0218 {
0219
0220
0221 BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_ortho, ortho_spheroid)
0222
0223
0224 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(ortho_entry, ortho_spheroid)
0225
0226 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(ortho_init)
0227 {
0228 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(ortho, ortho_entry)
0229 }
0230
0231 }
0232 #endif
0233
0234 }
0235
0236 }}
0237
0238 #endif
0239