123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526 |
- #ifndef BOOST_GEOMETRY_STRATEGIES_STRATEGY_TRANSFORM_HPP
- #define BOOST_GEOMETRY_STRATEGIES_STRATEGY_TRANSFORM_HPP
- #include <cstddef>
- #include <cmath>
- #include <functional>
- #include <boost/geometry/algorithms/convert.hpp>
- #include <boost/geometry/arithmetic/arithmetic.hpp>
- #include <boost/geometry/core/access.hpp>
- #include <boost/geometry/core/radian_access.hpp>
- #include <boost/geometry/core/coordinate_dimension.hpp>
- #include <boost/geometry/core/coordinate_promotion.hpp>
- #include <boost/geometry/strategies/transform.hpp>
- #include <boost/geometry/util/math.hpp>
- #include <boost/geometry/util/numeric_cast.hpp>
- #include <boost/geometry/util/select_coordinate_type.hpp>
- namespace boost { namespace geometry
- {
- namespace strategy { namespace transform
- {
- #ifndef DOXYGEN_NO_DETAIL
- namespace detail
- {
- template
- <
- typename Src, typename Dst,
- std::size_t D, std::size_t N,
- template <typename> class F
- >
- struct transform_coordinates
- {
- template <typename T>
- static inline void transform(Src const& source, Dst& dest, T value)
- {
- typedef typename select_coordinate_type<Src, Dst>::type coordinate_type;
- F<coordinate_type> function;
- set<D>(dest, util::numeric_cast<coordinate_type>(function(get<D>(source), value)));
- transform_coordinates<Src, Dst, D + 1, N, F>::transform(source, dest, value);
- }
- };
- template
- <
- typename Src, typename Dst,
- std::size_t N,
- template <typename> class F
- >
- struct transform_coordinates<Src, Dst, N, N, F>
- {
- template <typename T>
- static inline void transform(Src const& , Dst& , T )
- {
- }
- };
- }
- #endif
- template <typename P>
- struct copy_direct
- {
- inline bool apply(P const& p1, P& p2) const
- {
- p2 = p1;
- return true;
- }
- };
- template <typename P1, typename P2>
- struct copy_per_coordinate
- {
- inline bool apply(P1 const& p1, P2& p2) const
- {
-
- assert_dimension_equal<P1, P2>();
- geometry::convert(p1, p2);
- return true;
- }
- };
- template <typename P1, typename P2, template <typename> class F>
- struct degree_radian_vv
- {
- inline bool apply(P1 const& p1, P2& p2) const
- {
-
-
-
- assert_dimension<P1, 2>();
- assert_dimension<P2, 2>();
- typedef typename promote_floating_point
- <
- typename select_coordinate_type<P1, P2>::type
- >::type calculation_type;
- detail::transform_coordinates
- <
- P1, P2, 0, 2, F
- >::transform(p1, p2, math::d2r<calculation_type>());
- return true;
- }
- };
- template <typename P1, typename P2, template <typename> class F>
- struct degree_radian_vv_3
- {
- inline bool apply(P1 const& p1, P2& p2) const
- {
- assert_dimension<P1, 3>();
- assert_dimension<P2, 3>();
- typedef typename promote_floating_point
- <
- typename select_coordinate_type<P1, P2>::type
- >::type calculation_type;
- detail::transform_coordinates
- <
- P1, P2, 0, 2, F
- >::transform(p1, p2, math::d2r<calculation_type>());
-
- set<2>(p2, get<2>(p1));
- return true;
- }
- };
- #ifndef DOXYGEN_NO_DETAIL
- namespace detail
- {
-
- template <typename P, typename T, typename R>
- inline void spherical_polar_to_cartesian(T phi, T theta, R r, P& p)
- {
- assert_dimension<P, 3>();
-
-
-
-
-
-
- T r_sin_theta = r;
- T r_cos_theta = r;
- r_sin_theta *= sin(theta);
- r_cos_theta *= cos(theta);
- set<0>(p, r_sin_theta * cos(phi));
- set<1>(p, r_sin_theta * sin(phi));
- set<2>(p, r_cos_theta);
- }
-
- template <typename P, typename T, typename R>
- inline void spherical_equatorial_to_cartesian(T lambda, T delta, R r, P& p)
- {
- assert_dimension<P, 3>();
-
-
- T r_cos_delta = r;
- T r_sin_delta = r;
- r_cos_delta *= cos(delta);
- r_sin_delta *= sin(delta);
- set<0>(p, r_cos_delta * cos(lambda));
- set<1>(p, r_cos_delta * sin(lambda));
- set<2>(p, r_sin_delta);
- }
-
- template <typename P, typename T>
- inline bool cartesian_to_spherical2(T x, T y, T z, P& p)
- {
- assert_dimension<P, 2>();
-
- #if defined(BOOST_GEOMETRY_TRANSFORM_CHECK_UNIT_SPHERE)
-
- T const r = (x * x + y * y + z * z);
-
- if (geometry::math::abs(r - 1.0) > T(1e-6))
- {
- return false;
- }
-
- #endif
- set_from_radian<0>(p, atan2(y, x));
- set_from_radian<1>(p, acos(z));
- return true;
- }
- template <typename P, typename T>
- inline bool cartesian_to_spherical_equatorial2(T x, T y, T z, P& p)
- {
- assert_dimension<P, 2>();
- set_from_radian<0>(p, atan2(y, x));
- set_from_radian<1>(p, asin(z));
- return true;
- }
- template <typename P, typename T>
- inline bool cartesian_to_spherical3(T x, T y, T z, P& p)
- {
- assert_dimension<P, 3>();
-
- T const r = math::sqrt(x * x + y * y + z * z);
- set<2>(p, r);
- set_from_radian<0>(p, atan2(y, x));
- if (r > 0.0)
- {
- set_from_radian<1>(p, acos(z / r));
- return true;
- }
- return false;
- }
- template <typename P, typename T>
- inline bool cartesian_to_spherical_equatorial3(T x, T y, T z, P& p)
- {
- assert_dimension<P, 3>();
-
- T const r = math::sqrt(x * x + y * y + z * z);
- set<2>(p, r);
- set_from_radian<0>(p, atan2(y, x));
- if (r > 0.0)
- {
- set_from_radian<1>(p, asin(z / r));
- return true;
- }
- return false;
- }
- }
- #endif
- template <typename P1, typename P2>
- struct from_spherical_polar_2_to_cartesian_3
- {
- inline bool apply(P1 const& p1, P2& p2) const
- {
- assert_dimension<P1, 2>();
- detail::spherical_polar_to_cartesian(get_as_radian<0>(p1), get_as_radian<1>(p1), 1.0, p2);
- return true;
- }
- };
- template <typename P1, typename P2>
- struct from_spherical_equatorial_2_to_cartesian_3
- {
- inline bool apply(P1 const& p1, P2& p2) const
- {
- assert_dimension<P1, 2>();
- detail::spherical_equatorial_to_cartesian(get_as_radian<0>(p1), get_as_radian<1>(p1), 1.0, p2);
- return true;
- }
- };
- template <typename P1, typename P2>
- struct from_spherical_polar_3_to_cartesian_3
- {
- inline bool apply(P1 const& p1, P2& p2) const
- {
- assert_dimension<P1, 3>();
- detail::spherical_polar_to_cartesian(
- get_as_radian<0>(p1), get_as_radian<1>(p1), get<2>(p1), p2);
- return true;
- }
- };
- template <typename P1, typename P2>
- struct from_spherical_equatorial_3_to_cartesian_3
- {
- inline bool apply(P1 const& p1, P2& p2) const
- {
- assert_dimension<P1, 3>();
- detail::spherical_equatorial_to_cartesian(
- get_as_radian<0>(p1), get_as_radian<1>(p1), get<2>(p1), p2);
- return true;
- }
- };
- template <typename P1, typename P2>
- struct from_cartesian_3_to_spherical_polar_2
- {
- inline bool apply(P1 const& p1, P2& p2) const
- {
- assert_dimension<P1, 3>();
- return detail::cartesian_to_spherical2(get<0>(p1), get<1>(p1), get<2>(p1), p2);
- }
- };
- template <typename P1, typename P2>
- struct from_cartesian_3_to_spherical_equatorial_2
- {
- inline bool apply(P1 const& p1, P2& p2) const
- {
- assert_dimension<P1, 3>();
- return detail::cartesian_to_spherical_equatorial2(get<0>(p1), get<1>(p1), get<2>(p1), p2);
- }
- };
- template <typename P1, typename P2>
- struct from_cartesian_3_to_spherical_polar_3
- {
- inline bool apply(P1 const& p1, P2& p2) const
- {
- assert_dimension<P1, 3>();
- return detail::cartesian_to_spherical3(get<0>(p1), get<1>(p1), get<2>(p1), p2);
- }
- };
- template <typename P1, typename P2>
- struct from_cartesian_3_to_spherical_equatorial_3
- {
- inline bool apply(P1 const& p1, P2& p2) const
- {
- assert_dimension<P1, 3>();
- return detail::cartesian_to_spherical_equatorial3(get<0>(p1), get<1>(p1), get<2>(p1), p2);
- }
- };
- #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
- namespace services
- {
- template <typename CoordSysTag, typename CoordSys, std::size_t D, typename P>
- struct default_strategy<CoordSysTag, CoordSysTag, CoordSys, CoordSys, D, D, P, P>
- {
- typedef copy_direct<P> type;
- };
- template <typename CoordSysTag, typename CoordSys, std::size_t D, typename P1, typename P2>
- struct default_strategy<CoordSysTag, CoordSysTag, CoordSys, CoordSys, D, D, P1, P2>
- {
- typedef copy_per_coordinate<P1, P2> type;
- };
- template <typename CoordSysTag, template<typename> class CoordSys, typename P1, typename P2>
- struct default_strategy<CoordSysTag, CoordSysTag, CoordSys<degree>, CoordSys<radian>, 2, 2, P1, P2>
- {
- typedef degree_radian_vv<P1, P2, std::multiplies> type;
- };
- template <typename CoordSysTag, template<typename> class CoordSys, typename P1, typename P2>
- struct default_strategy<CoordSysTag, CoordSysTag, CoordSys<radian>, CoordSys<degree>, 2, 2, P1, P2>
- {
- typedef degree_radian_vv<P1, P2, std::divides> type;
- };
- template <typename CoordSysTag, template<typename> class CoordSys, typename P1, typename P2>
- struct default_strategy<CoordSysTag, CoordSysTag, CoordSys<degree>, CoordSys<radian>, 3, 3, P1, P2>
- {
- typedef degree_radian_vv_3<P1, P2, std::multiplies> type;
- };
- template <typename CoordSysTag, template<typename> class CoordSys, typename P1, typename P2>
- struct default_strategy<CoordSysTag, CoordSysTag, CoordSys<radian>, CoordSys<degree>, 3, 3, P1, P2>
- {
- typedef degree_radian_vv_3<P1, P2, std::divides> type;
- };
- template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>
- struct default_strategy<spherical_polar_tag, cartesian_tag, CoordSys1, CoordSys2, 2, 3, P1, P2>
- {
- typedef from_spherical_polar_2_to_cartesian_3<P1, P2> type;
- };
- template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>
- struct default_strategy<spherical_polar_tag, cartesian_tag, CoordSys1, CoordSys2, 3, 3, P1, P2>
- {
- typedef from_spherical_polar_3_to_cartesian_3<P1, P2> type;
- };
- template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>
- struct default_strategy<spherical_equatorial_tag, cartesian_tag, CoordSys1, CoordSys2, 2, 3, P1, P2>
- {
- typedef from_spherical_equatorial_2_to_cartesian_3<P1, P2> type;
- };
- template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>
- struct default_strategy<spherical_equatorial_tag, cartesian_tag, CoordSys1, CoordSys2, 3, 3, P1, P2>
- {
- typedef from_spherical_equatorial_3_to_cartesian_3<P1, P2> type;
- };
- template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>
- struct default_strategy<cartesian_tag, spherical_polar_tag, CoordSys1, CoordSys2, 3, 2, P1, P2>
- {
- typedef from_cartesian_3_to_spherical_polar_2<P1, P2> type;
- };
- template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>
- struct default_strategy<cartesian_tag, spherical_equatorial_tag, CoordSys1, CoordSys2, 3, 2, P1, P2>
- {
- typedef from_cartesian_3_to_spherical_equatorial_2<P1, P2> type;
- };
- template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>
- struct default_strategy<cartesian_tag, spherical_polar_tag, CoordSys1, CoordSys2, 3, 3, P1, P2>
- {
- typedef from_cartesian_3_to_spherical_polar_3<P1, P2> type;
- };
- template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>
- struct default_strategy<cartesian_tag, spherical_equatorial_tag, CoordSys1, CoordSys2, 3, 3, P1, P2>
- {
- typedef from_cartesian_3_to_spherical_equatorial_3<P1, P2> type;
- };
- }
- #endif
- }}
- }}
- #endif
|