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