123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487 |
- #ifndef BOOST_GEOMETRY_SRS_PROJECTIONS_IMPL_GEOCENT_HPP
- #define BOOST_GEOMETRY_SRS_PROJECTIONS_IMPL_GEOCENT_HPP
- #include <boost/geometry/util/math.hpp>
- namespace boost { namespace geometry { namespace projections
- {
- namespace detail
- {
- static const long GEOCENT_NO_ERROR = 0x0000;
- static const long GEOCENT_LAT_ERROR = 0x0001;
- static const long GEOCENT_LON_ERROR = 0x0002;
- static const long GEOCENT_A_ERROR = 0x0004;
- static const long GEOCENT_B_ERROR = 0x0008;
- static const long GEOCENT_A_LESS_B_ERROR = 0x0010;
- template <typename T>
- struct GeocentricInfo
- {
- T Geocent_a;
- T Geocent_b;
- T Geocent_a2;
- T Geocent_b2;
- T Geocent_e2;
- T Geocent_ep2;
- };
- template <typename T>
- inline T COS_67P5()
- {
- ;
- return cos(T(67.5) * math::d2r<T>());
- }
- template <typename T>
- inline T AD_C()
- {
- return 1.0026000;
- }
- template <typename T>
- inline long pj_Set_Geocentric_Parameters (GeocentricInfo<T> & gi, T const& a, T const& b)
- {
- long Error_Code = GEOCENT_NO_ERROR;
- if (a <= 0.0)
- Error_Code |= GEOCENT_A_ERROR;
- if (b <= 0.0)
- Error_Code |= GEOCENT_B_ERROR;
- if (a < b)
- Error_Code |= GEOCENT_A_LESS_B_ERROR;
- if (!Error_Code)
- {
- gi.Geocent_a = a;
- gi.Geocent_b = b;
- gi.Geocent_a2 = a * a;
- gi.Geocent_b2 = b * b;
- gi.Geocent_e2 = (gi.Geocent_a2 - gi.Geocent_b2) / gi.Geocent_a2;
- gi.Geocent_ep2 = (gi.Geocent_a2 - gi.Geocent_b2) / gi.Geocent_b2;
- }
- return (Error_Code);
- }
- template <typename T>
- inline void pj_Get_Geocentric_Parameters (GeocentricInfo<T> const& gi,
- T & a,
- T & b)
- {
- a = gi.Geocent_a;
- b = gi.Geocent_b;
- }
- template <typename T>
- inline long pj_Convert_Geodetic_To_Geocentric (GeocentricInfo<T> const& gi,
- T Longitude, T Latitude, T Height,
- T & X, T & Y, T & Z)
- {
- long Error_Code = GEOCENT_NO_ERROR;
- T Rn;
- T Sin_Lat;
- T Sin2_Lat;
- T Cos_Lat;
- static const T PI = math::pi<T>();
- static const T PI_OVER_2 = math::half_pi<T>();
-
- if( Latitude < -PI_OVER_2 && Latitude > -1.001 * PI_OVER_2 )
- Latitude = -PI_OVER_2;
- else if( Latitude > PI_OVER_2 && Latitude < 1.001 * PI_OVER_2 )
- Latitude = PI_OVER_2;
- else if ((Latitude < -PI_OVER_2) || (Latitude > PI_OVER_2))
- {
- Error_Code |= GEOCENT_LAT_ERROR;
- }
- if (!Error_Code)
- {
- if (Longitude > PI)
- Longitude -= (2*PI);
- Sin_Lat = sin(Latitude);
- Cos_Lat = cos(Latitude);
- Sin2_Lat = Sin_Lat * Sin_Lat;
- Rn = gi.Geocent_a / (sqrt(1.0e0 - gi.Geocent_e2 * Sin2_Lat));
- X = (Rn + Height) * Cos_Lat * cos(Longitude);
- Y = (Rn + Height) * Cos_Lat * sin(Longitude);
- Z = ((Rn * (1 - gi.Geocent_e2)) + Height) * Sin_Lat;
- }
- return (Error_Code);
- }
- #define BOOST_GEOMETRY_PROJECTIONS_USE_ITERATIVE_METHOD
- template <typename T>
- inline void pj_Convert_Geocentric_To_Geodetic (GeocentricInfo<T> const& gi,
- T X, T Y, T Z,
- T & Longitude, T & Latitude, T & Height)
- {
- static const T PI_OVER_2 = math::half_pi<T>();
- #if !defined(BOOST_GEOMETRY_PROJECTIONS_USE_ITERATIVE_METHOD)
- static const T COS_67P5 = detail::COS_67P5<T>();
- static const T AD_C = detail::AD_C<T>();
- T W;
- T W2;
- T T0;
- T T1;
- T S0;
- T S1;
- T Sin_B0;
- T Sin3_B0;
- T Cos_B0;
- T Sin_p1;
- T Cos_p1;
- T Rn;
- T Sum;
- bool At_Pole;
- At_Pole = false;
- if (X != 0.0)
- {
- Longitude = atan2(Y,X);
- }
- else
- {
- if (Y > 0)
- {
- Longitude = PI_OVER_2;
- }
- else if (Y < 0)
- {
- Longitude = -PI_OVER_2;
- }
- else
- {
- At_Pole = true;
- Longitude = 0.0;
- if (Z > 0.0)
- {
- Latitude = PI_OVER_2;
- }
- else if (Z < 0.0)
- {
- Latitude = -PI_OVER_2;
- }
- else
- {
- Latitude = PI_OVER_2;
- Height = -Geocent_b;
- return;
- }
- }
- }
- W2 = X*X + Y*Y;
- W = sqrt(W2);
- T0 = Z * AD_C;
- S0 = sqrt(T0 * T0 + W2);
- Sin_B0 = T0 / S0;
- Cos_B0 = W / S0;
- Sin3_B0 = Sin_B0 * Sin_B0 * Sin_B0;
- T1 = Z + gi.Geocent_b * gi.Geocent_ep2 * Sin3_B0;
- Sum = W - gi.Geocent_a * gi.Geocent_e2 * Cos_B0 * Cos_B0 * Cos_B0;
- S1 = sqrt(T1*T1 + Sum * Sum);
- Sin_p1 = T1 / S1;
- Cos_p1 = Sum / S1;
- Rn = gi.Geocent_a / sqrt(1.0 - gi.Geocent_e2 * Sin_p1 * Sin_p1);
- if (Cos_p1 >= COS_67P5)
- {
- Height = W / Cos_p1 - Rn;
- }
- else if (Cos_p1 <= -COS_67P5)
- {
- Height = W / -Cos_p1 - Rn;
- }
- else
- {
- Height = Z / Sin_p1 + Rn * (gi.Geocent_e2 - 1.0);
- }
- if (At_Pole == false)
- {
- Latitude = atan(Sin_p1 / Cos_p1);
- }
- #else
- static const T genau = 1.E-12;
- static const T genau2 = (genau*genau);
- static const int maxiter = 30;
- T P;
- T RR;
- T CT;
- T ST;
- T RX;
- T RK;
- T RN;
- T CPHI0;
- T SPHI0;
- T CPHI;
- T SPHI;
- T SDPHI;
- int iter;
- P = sqrt(X*X+Y*Y);
- RR = sqrt(X*X+Y*Y+Z*Z);
- if (P/gi.Geocent_a < genau) {
- Longitude = 0.;
- if (RR/gi.Geocent_a < genau) {
- Latitude = PI_OVER_2;
- Height = -gi.Geocent_b;
- return ;
- }
- }
- else {
- Longitude=atan2(Y,X);
- }
- CT = Z/RR;
- ST = P/RR;
- RX = 1.0/sqrt(1.0-gi.Geocent_e2*(2.0-gi.Geocent_e2)*ST*ST);
- CPHI0 = ST*(1.0-gi.Geocent_e2)*RX;
- SPHI0 = CT*RX;
- iter = 0;
- do
- {
- iter++;
- RN = gi.Geocent_a/sqrt(1.0-gi.Geocent_e2*SPHI0*SPHI0);
- Height = P*CPHI0+Z*SPHI0-RN*(1.0-gi.Geocent_e2*SPHI0*SPHI0);
- RK = gi.Geocent_e2*RN/(RN+Height);
- RX = 1.0/sqrt(1.0-RK*(2.0-RK)*ST*ST);
- CPHI = ST*(1.0-RK)*RX;
- SPHI = CT*RX;
- SDPHI = SPHI*CPHI0-CPHI*SPHI0;
- CPHI0 = CPHI;
- SPHI0 = SPHI;
- }
- while (SDPHI*SDPHI > genau2 && iter < maxiter);
- Latitude=atan(SPHI/fabs(CPHI));
- return;
- #endif
- }
- }
- }}}
- #endif
|