File indexing completed on 2025-01-18 09:36:50
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019 #ifndef BOOST_GEOMETRY_STRATEGIES_STRATEGY_TRANSFORM_HPP
0020 #define BOOST_GEOMETRY_STRATEGIES_STRATEGY_TRANSFORM_HPP
0021
0022 #include <cstddef>
0023 #include <cmath>
0024 #include <functional>
0025
0026 #include <boost/numeric/conversion/cast.hpp>
0027
0028 #include <boost/geometry/algorithms/convert.hpp>
0029 #include <boost/geometry/arithmetic/arithmetic.hpp>
0030 #include <boost/geometry/core/access.hpp>
0031 #include <boost/geometry/core/radian_access.hpp>
0032 #include <boost/geometry/core/coordinate_dimension.hpp>
0033 #include <boost/geometry/core/coordinate_promotion.hpp>
0034 #include <boost/geometry/strategies/transform.hpp>
0035
0036 #include <boost/geometry/util/math.hpp>
0037 #include <boost/geometry/util/select_coordinate_type.hpp>
0038
0039 namespace boost { namespace geometry
0040 {
0041
0042 namespace strategy { namespace transform
0043 {
0044
0045 #ifndef DOXYGEN_NO_DETAIL
0046 namespace detail
0047 {
0048
0049 template
0050 <
0051 typename Src, typename Dst,
0052 std::size_t D, std::size_t N,
0053 template <typename> class F
0054 >
0055 struct transform_coordinates
0056 {
0057 template <typename T>
0058 static inline void transform(Src const& source, Dst& dest, T value)
0059 {
0060 typedef typename select_coordinate_type<Src, Dst>::type coordinate_type;
0061
0062 F<coordinate_type> function;
0063 set<D>(dest, boost::numeric_cast<coordinate_type>(function(get<D>(source), value)));
0064 transform_coordinates<Src, Dst, D + 1, N, F>::transform(source, dest, value);
0065 }
0066 };
0067
0068 template
0069 <
0070 typename Src, typename Dst,
0071 std::size_t N,
0072 template <typename> class F
0073 >
0074 struct transform_coordinates<Src, Dst, N, N, F>
0075 {
0076 template <typename T>
0077 static inline void transform(Src const& , Dst& , T )
0078 {
0079 }
0080 };
0081
0082 }
0083 #endif
0084
0085
0086
0087
0088
0089
0090
0091 template <typename P>
0092 struct copy_direct
0093 {
0094 inline bool apply(P const& p1, P& p2) const
0095 {
0096 p2 = p1;
0097 return true;
0098 }
0099 };
0100
0101
0102
0103
0104
0105
0106
0107 template <typename P1, typename P2>
0108 struct copy_per_coordinate
0109 {
0110 inline bool apply(P1 const& p1, P2& p2) const
0111 {
0112
0113 assert_dimension_equal<P1, P2>();
0114
0115 geometry::convert(p1, p2);
0116 return true;
0117 }
0118 };
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128 template <typename P1, typename P2, template <typename> class F>
0129 struct degree_radian_vv
0130 {
0131 inline bool apply(P1 const& p1, P2& p2) const
0132 {
0133
0134
0135
0136 assert_dimension<P1, 2>();
0137 assert_dimension<P2, 2>();
0138
0139 typedef typename promote_floating_point
0140 <
0141 typename select_coordinate_type<P1, P2>::type
0142 >::type calculation_type;
0143
0144 detail::transform_coordinates
0145 <
0146 P1, P2, 0, 2, F
0147 >::transform(p1, p2, math::d2r<calculation_type>());
0148 return true;
0149 }
0150 };
0151
0152 template <typename P1, typename P2, template <typename> class F>
0153 struct degree_radian_vv_3
0154 {
0155 inline bool apply(P1 const& p1, P2& p2) const
0156 {
0157 assert_dimension<P1, 3>();
0158 assert_dimension<P2, 3>();
0159
0160 typedef typename promote_floating_point
0161 <
0162 typename select_coordinate_type<P1, P2>::type
0163 >::type calculation_type;
0164
0165 detail::transform_coordinates
0166 <
0167 P1, P2, 0, 2, F
0168 >::transform(p1, p2, math::d2r<calculation_type>());
0169
0170
0171 set<2>(p2, get<2>(p1));
0172 return true;
0173 }
0174 };
0175
0176
0177 #ifndef DOXYGEN_NO_DETAIL
0178 namespace detail
0179 {
0180
0181
0182 template <typename P, typename T, typename R>
0183 inline void spherical_polar_to_cartesian(T phi, T theta, R r, P& p)
0184 {
0185 assert_dimension<P, 3>();
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196 T r_sin_theta = r;
0197 T r_cos_theta = r;
0198 r_sin_theta *= sin(theta);
0199 r_cos_theta *= cos(theta);
0200
0201 set<0>(p, r_sin_theta * cos(phi));
0202 set<1>(p, r_sin_theta * sin(phi));
0203 set<2>(p, r_cos_theta);
0204 }
0205
0206
0207 template <typename P, typename T, typename R>
0208 inline void spherical_equatorial_to_cartesian(T lambda, T delta, R r, P& p)
0209 {
0210 assert_dimension<P, 3>();
0211
0212
0213
0214
0215 T r_cos_delta = r;
0216 T r_sin_delta = r;
0217 r_cos_delta *= cos(delta);
0218 r_sin_delta *= sin(delta);
0219
0220 set<0>(p, r_cos_delta * cos(lambda));
0221 set<1>(p, r_cos_delta * sin(lambda));
0222 set<2>(p, r_sin_delta);
0223 }
0224
0225
0226
0227 template <typename P, typename T>
0228 inline bool cartesian_to_spherical2(T x, T y, T z, P& p)
0229 {
0230 assert_dimension<P, 2>();
0231
0232
0233
0234 #if defined(BOOST_GEOMETRY_TRANSFORM_CHECK_UNIT_SPHERE)
0235
0236 T const r = (x * x + y * y + z * z);
0237
0238
0239 if (geometry::math::abs(r - 1.0) > T(1e-6))
0240 {
0241 return false;
0242 }
0243
0244 #endif
0245
0246 set_from_radian<0>(p, atan2(y, x));
0247 set_from_radian<1>(p, acos(z));
0248 return true;
0249 }
0250
0251 template <typename P, typename T>
0252 inline bool cartesian_to_spherical_equatorial2(T x, T y, T z, P& p)
0253 {
0254 assert_dimension<P, 2>();
0255
0256 set_from_radian<0>(p, atan2(y, x));
0257 set_from_radian<1>(p, asin(z));
0258 return true;
0259 }
0260
0261
0262 template <typename P, typename T>
0263 inline bool cartesian_to_spherical3(T x, T y, T z, P& p)
0264 {
0265 assert_dimension<P, 3>();
0266
0267
0268 T const r = math::sqrt(x * x + y * y + z * z);
0269 set<2>(p, r);
0270 set_from_radian<0>(p, atan2(y, x));
0271 if (r > 0.0)
0272 {
0273 set_from_radian<1>(p, acos(z / r));
0274 return true;
0275 }
0276 return false;
0277 }
0278
0279 template <typename P, typename T>
0280 inline bool cartesian_to_spherical_equatorial3(T x, T y, T z, P& p)
0281 {
0282 assert_dimension<P, 3>();
0283
0284
0285 T const r = math::sqrt(x * x + y * y + z * z);
0286 set<2>(p, r);
0287 set_from_radian<0>(p, atan2(y, x));
0288 if (r > 0.0)
0289 {
0290 set_from_radian<1>(p, asin(z / r));
0291 return true;
0292 }
0293 return false;
0294 }
0295
0296 }
0297 #endif
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307 template <typename P1, typename P2>
0308 struct from_spherical_polar_2_to_cartesian_3
0309 {
0310 inline bool apply(P1 const& p1, P2& p2) const
0311 {
0312 assert_dimension<P1, 2>();
0313 detail::spherical_polar_to_cartesian(get_as_radian<0>(p1), get_as_radian<1>(p1), 1.0, p2);
0314 return true;
0315 }
0316 };
0317
0318 template <typename P1, typename P2>
0319 struct from_spherical_equatorial_2_to_cartesian_3
0320 {
0321 inline bool apply(P1 const& p1, P2& p2) const
0322 {
0323 assert_dimension<P1, 2>();
0324 detail::spherical_equatorial_to_cartesian(get_as_radian<0>(p1), get_as_radian<1>(p1), 1.0, p2);
0325 return true;
0326 }
0327 };
0328
0329
0330
0331
0332
0333
0334
0335
0336 template <typename P1, typename P2>
0337 struct from_spherical_polar_3_to_cartesian_3
0338 {
0339 inline bool apply(P1 const& p1, P2& p2) const
0340 {
0341 assert_dimension<P1, 3>();
0342 detail::spherical_polar_to_cartesian(
0343 get_as_radian<0>(p1), get_as_radian<1>(p1), get<2>(p1), p2);
0344 return true;
0345 }
0346 };
0347
0348 template <typename P1, typename P2>
0349 struct from_spherical_equatorial_3_to_cartesian_3
0350 {
0351 inline bool apply(P1 const& p1, P2& p2) const
0352 {
0353 assert_dimension<P1, 3>();
0354 detail::spherical_equatorial_to_cartesian(
0355 get_as_radian<0>(p1), get_as_radian<1>(p1), get<2>(p1), p2);
0356 return true;
0357 }
0358 };
0359
0360
0361
0362
0363
0364
0365
0366
0367
0368
0369 template <typename P1, typename P2>
0370 struct from_cartesian_3_to_spherical_polar_2
0371 {
0372 inline bool apply(P1 const& p1, P2& p2) const
0373 {
0374 assert_dimension<P1, 3>();
0375 return detail::cartesian_to_spherical2(get<0>(p1), get<1>(p1), get<2>(p1), p2);
0376 }
0377 };
0378
0379 template <typename P1, typename P2>
0380 struct from_cartesian_3_to_spherical_equatorial_2
0381 {
0382 inline bool apply(P1 const& p1, P2& p2) const
0383 {
0384 assert_dimension<P1, 3>();
0385 return detail::cartesian_to_spherical_equatorial2(get<0>(p1), get<1>(p1), get<2>(p1), p2);
0386 }
0387 };
0388
0389
0390
0391
0392
0393
0394
0395
0396 template <typename P1, typename P2>
0397 struct from_cartesian_3_to_spherical_polar_3
0398 {
0399 inline bool apply(P1 const& p1, P2& p2) const
0400 {
0401 assert_dimension<P1, 3>();
0402 return detail::cartesian_to_spherical3(get<0>(p1), get<1>(p1), get<2>(p1), p2);
0403 }
0404 };
0405
0406 template <typename P1, typename P2>
0407 struct from_cartesian_3_to_spherical_equatorial_3
0408 {
0409 inline bool apply(P1 const& p1, P2& p2) const
0410 {
0411 assert_dimension<P1, 3>();
0412 return detail::cartesian_to_spherical_equatorial3(get<0>(p1), get<1>(p1), get<2>(p1), p2);
0413 }
0414 };
0415
0416 #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
0417
0418 namespace services
0419 {
0420
0421
0422 template <typename CoordSysTag, typename CoordSys, std::size_t D, typename P>
0423 struct default_strategy<CoordSysTag, CoordSysTag, CoordSys, CoordSys, D, D, P, P>
0424 {
0425 typedef copy_direct<P> type;
0426 };
0427
0428
0429 template <typename CoordSysTag, typename CoordSys, std::size_t D, typename P1, typename P2>
0430 struct default_strategy<CoordSysTag, CoordSysTag, CoordSys, CoordSys, D, D, P1, P2>
0431 {
0432 typedef copy_per_coordinate<P1, P2> type;
0433 };
0434
0435
0436 template <typename CoordSysTag, template<typename> class CoordSys, typename P1, typename P2>
0437 struct default_strategy<CoordSysTag, CoordSysTag, CoordSys<degree>, CoordSys<radian>, 2, 2, P1, P2>
0438 {
0439 typedef degree_radian_vv<P1, P2, std::multiplies> type;
0440 };
0441
0442
0443 template <typename CoordSysTag, template<typename> class CoordSys, typename P1, typename P2>
0444 struct default_strategy<CoordSysTag, CoordSysTag, CoordSys<radian>, CoordSys<degree>, 2, 2, P1, P2>
0445 {
0446 typedef degree_radian_vv<P1, P2, std::divides> type;
0447 };
0448
0449
0450
0451 template <typename CoordSysTag, template<typename> class CoordSys, typename P1, typename P2>
0452 struct default_strategy<CoordSysTag, CoordSysTag, CoordSys<degree>, CoordSys<radian>, 3, 3, P1, P2>
0453 {
0454 typedef degree_radian_vv_3<P1, P2, std::multiplies> type;
0455 };
0456
0457
0458 template <typename CoordSysTag, template<typename> class CoordSys, typename P1, typename P2>
0459 struct default_strategy<CoordSysTag, CoordSysTag, CoordSys<radian>, CoordSys<degree>, 3, 3, P1, P2>
0460 {
0461 typedef degree_radian_vv_3<P1, P2, std::divides> type;
0462 };
0463
0464
0465 template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>
0466 struct default_strategy<spherical_polar_tag, cartesian_tag, CoordSys1, CoordSys2, 2, 3, P1, P2>
0467 {
0468 typedef from_spherical_polar_2_to_cartesian_3<P1, P2> type;
0469 };
0470
0471
0472 template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>
0473 struct default_strategy<spherical_polar_tag, cartesian_tag, CoordSys1, CoordSys2, 3, 3, P1, P2>
0474 {
0475 typedef from_spherical_polar_3_to_cartesian_3<P1, P2> type;
0476 };
0477
0478 template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>
0479 struct default_strategy<spherical_equatorial_tag, cartesian_tag, CoordSys1, CoordSys2, 2, 3, P1, P2>
0480 {
0481 typedef from_spherical_equatorial_2_to_cartesian_3<P1, P2> type;
0482 };
0483
0484 template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>
0485 struct default_strategy<spherical_equatorial_tag, cartesian_tag, CoordSys1, CoordSys2, 3, 3, P1, P2>
0486 {
0487 typedef from_spherical_equatorial_3_to_cartesian_3<P1, P2> type;
0488 };
0489
0490
0491 template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>
0492 struct default_strategy<cartesian_tag, spherical_polar_tag, CoordSys1, CoordSys2, 3, 2, P1, P2>
0493 {
0494 typedef from_cartesian_3_to_spherical_polar_2<P1, P2> type;
0495 };
0496
0497 template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>
0498 struct default_strategy<cartesian_tag, spherical_equatorial_tag, CoordSys1, CoordSys2, 3, 2, P1, P2>
0499 {
0500 typedef from_cartesian_3_to_spherical_equatorial_2<P1, P2> type;
0501 };
0502
0503
0504 template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>
0505 struct default_strategy<cartesian_tag, spherical_polar_tag, CoordSys1, CoordSys2, 3, 3, P1, P2>
0506 {
0507 typedef from_cartesian_3_to_spherical_polar_3<P1, P2> type;
0508 };
0509 template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>
0510 struct default_strategy<cartesian_tag, spherical_equatorial_tag, CoordSys1, CoordSys2, 3, 3, P1, P2>
0511 {
0512 typedef from_cartesian_3_to_spherical_equatorial_3<P1, P2> type;
0513 };
0514
0515
0516 }
0517
0518
0519 #endif
0520
0521
0522 }}
0523
0524
0525 }}
0526
0527 #endif