123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 |
- #ifndef BOOST_GEOMETRY_FORMULAS_GNOMONIC_SPHEROID_HPP
- #define BOOST_GEOMETRY_FORMULAS_GNOMONIC_SPHEROID_HPP
- #include <boost/geometry/core/radius.hpp>
- #include <boost/geometry/util/condition.hpp>
- #include <boost/geometry/util/math.hpp>
- #include <boost/geometry/formulas/andoyer_inverse.hpp>
- #include <boost/geometry/formulas/flattening.hpp>
- #include <boost/geometry/formulas/thomas_inverse.hpp>
- #include <boost/geometry/formulas/vincenty_direct.hpp>
- #include <boost/geometry/formulas/vincenty_inverse.hpp>
- namespace boost { namespace geometry { namespace formula
- {
- template <
- typename CT,
- template <typename, bool, bool, bool, bool ,bool> class Inverse,
- template <typename, bool, bool, bool, bool> class Direct
- >
- class gnomonic_spheroid
- {
- typedef Inverse<CT, false, true, true, true, true> inverse_type;
- typedef typename inverse_type::result_type inverse_result;
- typedef Direct<CT, false, false, true, true> direct_quantities_type;
- typedef Direct<CT, true, false, false, false> direct_coordinates_type;
- typedef typename direct_coordinates_type::result_type direct_result;
- public:
- template <typename Spheroid>
- static inline bool forward(CT const& lon0, CT const& lat0,
- CT const& lon, CT const& lat,
- CT & x, CT & y,
- Spheroid const& spheroid)
- {
- inverse_result i_res = inverse_type::apply(lon0, lat0, lon, lat, spheroid);
- CT const& m = i_res.reduced_length;
- CT const& M = i_res.geodesic_scale;
- if (math::smaller_or_equals(M, CT(0)))
- {
- return false;
- }
- CT rho = m / M;
- x = sin(i_res.azimuth) * rho;
- y = cos(i_res.azimuth) * rho;
- return true;
- }
- template <typename Spheroid>
- static inline bool inverse(CT const& lon0, CT const& lat0,
- CT const& x, CT const& y,
- CT & lon, CT & lat,
- Spheroid const& spheroid)
- {
- CT const a = get_radius<0>(spheroid);
- CT const ds_threshold = a * std::numeric_limits<CT>::epsilon();
- CT const azimuth = atan2(x, y);
- CT const rho = math::sqrt(math::sqr(x) + math::sqr(y));
- CT distance = a * atan(rho / a);
- bool found = false;
- for (int i = 0 ; i < 10 ; ++i)
- {
- direct_result d_res = direct_quantities_type::apply(lon0, lat0, distance, azimuth, spheroid);
- CT const& m = d_res.reduced_length;
- CT const& M = d_res.geodesic_scale;
- if (math::smaller_or_equals(M, CT(0)))
- {
-
- return found;
- }
- CT const drho = m / M - rho;
- CT const ds = drho * math::sqr(M);
- distance -= ds;
-
- if (math::abs(ds) <= ds_threshold)
- {
- found = true;
- break;
- }
- }
- if (found)
- {
- direct_result d_res = direct_coordinates_type::apply(lon0, lat0, distance, azimuth, spheroid);
- lon = d_res.lon2;
- lat = d_res.lat2;
- }
- return found;
- }
- };
- }}}
- #endif
|