123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 |
- #ifndef BOOST_GEOMETRY_FORMULAS_MERIDIAN_DIRECT_HPP
- #define BOOST_GEOMETRY_FORMULAS_MERIDIAN_DIRECT_HPP
- #include <boost/math/constants/constants.hpp>
- #include <boost/geometry/core/radius.hpp>
- #include <boost/geometry/formulas/differential_quantities.hpp>
- #include <boost/geometry/formulas/flattening.hpp>
- #include <boost/geometry/formulas/meridian_inverse.hpp>
- #include <boost/geometry/formulas/quarter_meridian.hpp>
- #include <boost/geometry/formulas/result_direct.hpp>
- #include <boost/geometry/util/constexpr.hpp>
- #include <boost/geometry/util/math.hpp>
- namespace boost { namespace geometry { namespace formula
- {
- template <
- typename CT,
- bool EnableCoordinates = true,
- bool EnableReverseAzimuth = false,
- bool EnableReducedLength = false,
- bool EnableGeodesicScale = false,
- unsigned int Order = 4
- >
- class meridian_direct
- {
- static const bool CalcQuantities = EnableReducedLength || EnableGeodesicScale;
- static const bool CalcRevAzimuth = EnableReverseAzimuth || CalcQuantities;
- static const bool CalcCoordinates = EnableCoordinates || CalcRevAzimuth;
- public:
- typedef result_direct<CT> result_type;
- template <typename T, typename Dist, typename Spheroid>
- static inline result_type apply(T const& lo1,
- T const& la1,
- Dist const& distance,
- bool north,
- Spheroid const& spheroid)
- {
- result_type result;
- CT const half_pi = math::half_pi<CT>();
- CT const pi = math::pi<CT>();
- CT const one_and_a_half_pi = pi + half_pi;
- CT const c0 = 0;
- CT azimuth = north ? c0 : pi;
- if BOOST_GEOMETRY_CONSTEXPR (CalcCoordinates)
- {
- CT s0 = meridian_inverse<CT, Order>::apply(la1, spheroid);
- int signed_distance = north ? distance : -distance;
- result.lon2 = lo1;
- result.lat2 = apply(s0 + signed_distance, spheroid);
- }
- if BOOST_GEOMETRY_CONSTEXPR (CalcRevAzimuth)
- {
- result.reverse_azimuth = azimuth;
- if (result.lat2 > half_pi &&
- result.lat2 < one_and_a_half_pi)
- {
- result.reverse_azimuth = pi;
- }
- else if (result.lat2 > -one_and_a_half_pi &&
- result.lat2 < -half_pi)
- {
- result.reverse_azimuth = c0;
- }
- }
- if BOOST_GEOMETRY_CONSTEXPR (CalcQuantities)
- {
- CT const b = CT(get_radius<2>(spheroid));
- CT const f = formula::flattening<CT>(spheroid);
- boost::geometry::math::normalize_spheroidal_coordinates
- <
- boost::geometry::radian,
- double
- >(result.lon2, result.lat2);
- typedef differential_quantities
- <
- CT,
- EnableReducedLength,
- EnableGeodesicScale,
- Order
- > quantities;
- quantities::apply(lo1, la1, result.lon2, result.lat2,
- azimuth, result.reverse_azimuth,
- b, f,
- result.reduced_length, result.geodesic_scale);
- }
- return result;
- }
-
-
- template <typename T, typename Spheroid>
- static CT apply(T m, Spheroid const& spheroid)
- {
- CT const f = formula::flattening<CT>(spheroid);
- CT n = f / (CT(2) - f);
- CT mp = formula::quarter_meridian<CT>(spheroid);
- CT mu = geometry::math::pi<CT>()/CT(2) * m / mp;
- if (BOOST_GEOMETRY_CONDITION(Order == 0))
- {
- return mu;
- }
- CT H2 = 1.5 * n;
- if (BOOST_GEOMETRY_CONDITION(Order == 1))
- {
- return mu + H2 * sin(2*mu);
- }
- CT n2 = n * n;
- CT H4 = 1.3125 * n2;
- if (BOOST_GEOMETRY_CONDITION(Order == 2))
- {
- return mu + H2 * sin(2*mu) + H4 * sin(4*mu);
- }
- CT n3 = n2 * n;
- H2 -= 0.84375 * n3;
- CT H6 = 1.572916667 * n3;
- if (BOOST_GEOMETRY_CONDITION(Order == 3))
- {
- return mu + H2 * sin(2*mu) + H4 * sin(4*mu) + H6 * sin(6*mu);
- }
- CT n4 = n2 * n2;
- H4 -= 1.71875 * n4;
- CT H8 = 2.142578125 * n4;
-
- return mu + H2 * sin(2*mu) + H4 * sin(4*mu) + H6 * sin(6*mu) + H8 * sin(8*mu);
- }
- };
- }}}
- #endif
|