Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-11 08:12:23

0001 // Boost.Geometry (aka GGL, Generic Geometry Library)
0002 
0003 // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
0004 // Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
0005 // Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
0006 
0007 // This file was modified by Oracle on 2015.
0008 // Modifications copyright (c) 2015 Oracle and/or its affiliates.
0009 
0010 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
0011 
0012 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
0013 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
0014 
0015 // Use, modification and distribution is subject to the Boost Software License,
0016 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0017 // http://www.boost.org/LICENSE_1_0.txt)
0018 
0019 #ifndef BOOST_GEOMETRY_STRATEGIES_TRANSFORM_MATRIX_TRANSFORMERS_HPP
0020 #define BOOST_GEOMETRY_STRATEGIES_TRANSFORM_MATRIX_TRANSFORMERS_HPP
0021 
0022 
0023 #include <cstddef>
0024 
0025 #include <boost/qvm/mat.hpp>
0026 #include <boost/qvm/vec.hpp>
0027 #include <boost/qvm/mat_access.hpp>
0028 #include <boost/qvm/vec_access.hpp>
0029 #include <boost/qvm/mat_operations.hpp>
0030 #include <boost/qvm/vec_mat_operations.hpp>
0031 #include <boost/qvm/map_mat_mat.hpp>
0032 #include <boost/qvm/map_mat_vec.hpp>
0033 
0034 #include <boost/geometry/core/access.hpp>
0035 #include <boost/geometry/core/coordinate_dimension.hpp>
0036 #include <boost/geometry/core/coordinate_promotion.hpp>
0037 #include <boost/geometry/core/cs.hpp>
0038 #include <boost/geometry/util/math.hpp>
0039 #include <boost/geometry/util/numeric_cast.hpp>
0040 #include <boost/geometry/util/select_coordinate_type.hpp>
0041 #include <boost/geometry/util/select_most_precise.hpp>
0042 
0043 
0044 namespace boost { namespace geometry
0045 {
0046 
0047 namespace strategy { namespace transform
0048 {
0049 
0050 namespace detail { namespace matrix_transformer
0051 {
0052 
0053 template
0054 <
0055     typename Point,
0056     std::size_t Dimension = 0,
0057     std::size_t DimensionCount = geometry::dimension<Point>::value
0058 >
0059 struct set_point_from_vec
0060 {
0061     template <typename Vector>
0062     static inline void apply(Point & p, Vector const& v)
0063     {
0064         typedef typename geometry::coordinate_type<Point>::type coord_t;
0065         set<Dimension>(p, util::numeric_cast<coord_t>(qvm::A<Dimension>(v)));
0066         set_point_from_vec<Point, Dimension + 1, DimensionCount>::apply(p, v);
0067     }
0068 };
0069 
0070 template
0071 <
0072     typename Point,
0073     std::size_t DimensionCount
0074 >
0075 struct set_point_from_vec<Point, DimensionCount, DimensionCount>
0076 {
0077     template <typename Vector>
0078     static inline void apply(Point &, Vector const&) {}
0079 };
0080 
0081 template
0082 <
0083     typename Point,
0084     std::size_t Dimension = 0,
0085     std::size_t DimensionCount = geometry::dimension<Point>::value
0086 >
0087 struct set_vec_from_point
0088 {
0089     template <typename Vector>
0090     static inline void apply(Point const& p, Vector & v)
0091     {
0092         qvm::A<Dimension>(v) = get<Dimension>(p);
0093         set_vec_from_point<Point, Dimension + 1, DimensionCount>::apply(p, v);
0094     }
0095 };
0096 
0097 template
0098 <
0099     typename Point,
0100     std::size_t DimensionCount
0101 >
0102 struct set_vec_from_point<Point, DimensionCount, DimensionCount>
0103 {
0104     template <typename Vector>
0105     static inline void apply(Point const&, Vector &) {}
0106 };
0107 
0108 template
0109 <
0110     typename CalculationType,
0111     std::size_t Dimension1,
0112     std::size_t Dimension2
0113 >
0114 class matrix_transformer
0115 {
0116 protected :
0117     typedef CalculationType ct;
0118     typedef boost::qvm::mat<ct, Dimension2 + 1, Dimension1 + 1> matrix_type;
0119     matrix_type m_matrix;
0120 public :
0121     matrix_type const& matrix() const { return m_matrix; }
0122     template <typename P1, typename P2>
0123     inline bool apply(P1 const& p1, P2& p2) const
0124     {
0125         assert_dimension_greater_equal<P1,Dimension1>();
0126         assert_dimension_greater_equal<P2,Dimension2>();
0127         qvm::vec<ct,Dimension1 + 1> p1temp;
0128         qvm::A<Dimension1>(p1temp) = 1;
0129         qvm::vec<ct,Dimension2 + 1> p2temp;
0130         set_vec_from_point<P1, 0, Dimension1>::apply(p1, p1temp);
0131         p2temp = m_matrix * p1temp;
0132         set_point_from_vec<P2, 0, Dimension2>::apply(p2, p2temp);
0133         return true;
0134     }
0135 
0136 };
0137 
0138 }} // namespace detail::matrix_transform
0139 
0140 /*!
0141 \brief Affine transformation strategy in Cartesian system.
0142 \details The strategy serves as a generic definition of an affine transformation
0143          matrix and procedure for applying it to a given point.
0144 \see http://en.wikipedia.org/wiki/Affine_transformation
0145      and http://www.devmaster.net/wiki/Transformation_matrices
0146 \ingroup strategies
0147 \tparam Dimension1 number of dimensions to transform from
0148 \tparam Dimension2 number of dimensions to transform to
0149  */
0150 template
0151 <
0152     typename CalculationType,
0153     std::size_t Dimension1,
0154     std::size_t Dimension2
0155 >
0156 class matrix_transformer : public detail::matrix_transformer::matrix_transformer<CalculationType, Dimension1, Dimension2>
0157 {
0158 public:
0159     template<typename Matrix>
0160     inline matrix_transformer(Matrix const& matrix)
0161     {
0162         qvm::assign(this->m_matrix, matrix);
0163     }
0164     inline matrix_transformer() {}
0165 };
0166 
0167 
0168 template <typename CalculationType>
0169 class matrix_transformer<CalculationType, 2, 2> : public detail::matrix_transformer::matrix_transformer<CalculationType, 2, 2>
0170 {
0171     typedef CalculationType ct;
0172 public :
0173     template<typename Matrix>
0174     inline matrix_transformer(Matrix const& matrix)
0175     {
0176         qvm::assign(this->m_matrix, matrix);
0177     }
0178 
0179     inline matrix_transformer() {}
0180 
0181     inline matrix_transformer(
0182                 ct const& m_0_0, ct const& m_0_1, ct const& m_0_2,
0183                 ct const& m_1_0, ct const& m_1_1, ct const& m_1_2,
0184                 ct const& m_2_0, ct const& m_2_1, ct const& m_2_2)
0185     {
0186         qvm::A<0,0>(this->m_matrix) = m_0_0;   qvm::A<0,1>(this->m_matrix) = m_0_1;   qvm::A<0,2>(this->m_matrix) = m_0_2;
0187         qvm::A<1,0>(this->m_matrix) = m_1_0;   qvm::A<1,1>(this->m_matrix) = m_1_1;   qvm::A<1,2>(this->m_matrix) = m_1_2;
0188         qvm::A<2,0>(this->m_matrix) = m_2_0;   qvm::A<2,1>(this->m_matrix) = m_2_1;   qvm::A<2,2>(this->m_matrix) = m_2_2;
0189     }
0190 
0191     template <typename P1, typename P2>
0192     inline bool apply(P1 const& p1, P2& p2) const
0193     {
0194         assert_dimension_greater_equal<P1, 2>();
0195         assert_dimension_greater_equal<P2, 2>();
0196 
0197         ct const& c1 = get<0>(p1);
0198         ct const& c2 = get<1>(p1);
0199 
0200         typedef typename geometry::coordinate_type<P2>::type ct2;
0201         set<0>(p2, util::numeric_cast<ct2>(c1 * qvm::A<0,0>(this->m_matrix) + c2 * qvm::A<0,1>(this->m_matrix) + qvm::A<0,2>(this->m_matrix)));
0202         set<1>(p2, util::numeric_cast<ct2>(c1 * qvm::A<1,0>(this->m_matrix) + c2 * qvm::A<1,1>(this->m_matrix) + qvm::A<1,2>(this->m_matrix)));
0203 
0204         return true;
0205     }
0206 };
0207 
0208 
0209 // It IS possible to go from 3 to 2 coordinates
0210 template <typename CalculationType>
0211 class matrix_transformer<CalculationType, 3, 2> : public detail::matrix_transformer::matrix_transformer<CalculationType, 3, 2>
0212 {
0213     typedef CalculationType ct;
0214 public :
0215     template<typename Matrix>
0216     inline matrix_transformer(Matrix const& matrix)
0217     {
0218         qvm::assign(this->m_matrix, matrix);
0219     }
0220 
0221     inline matrix_transformer() {}
0222 
0223     inline matrix_transformer(
0224                 ct const& m_0_0, ct const& m_0_1, ct const& m_0_2,
0225                 ct const& m_1_0, ct const& m_1_1, ct const& m_1_2,
0226                 ct const& m_2_0, ct const& m_2_1, ct const& m_2_2)
0227     {
0228         qvm::A<0,0>(this->m_matrix) = m_0_0;   qvm::A<0,1>(this->m_matrix) = m_0_1;   qvm::A<0,2>(this->m_matrix) = 0;   qvm::A<0,3>(this->m_matrix) = m_0_2;
0229         qvm::A<1,0>(this->m_matrix) = m_1_0;   qvm::A<1,1>(this->m_matrix) = m_1_1;   qvm::A<1,2>(this->m_matrix) = 0;   qvm::A<1,3>(this->m_matrix) = m_1_2;
0230         qvm::A<2,0>(this->m_matrix) = m_2_0;   qvm::A<2,1>(this->m_matrix) = m_2_1;   qvm::A<2,2>(this->m_matrix) = 0;   qvm::A<2,3>(this->m_matrix) = m_2_2;
0231     }
0232 
0233     template <typename P1, typename P2>
0234     inline bool apply(P1 const& p1, P2& p2) const
0235     {
0236         assert_dimension_greater_equal<P1, 3>();
0237         assert_dimension_greater_equal<P2, 2>();
0238 
0239         ct const& c1 = get<0>(p1);
0240         ct const& c2 = get<1>(p1);
0241         ct const& c3 = get<2>(p1);
0242 
0243         typedef typename geometry::coordinate_type<P2>::type ct2;
0244 
0245         set<0>(p2, util::numeric_cast<ct2>(
0246             c1 * qvm::A<0,0>(this->m_matrix) + c2 * qvm::A<0,1>(this->m_matrix) + c3 * qvm::A<0,2>(this->m_matrix) + qvm::A<0,3>(this->m_matrix)));
0247         set<1>(p2, util::numeric_cast<ct2>(
0248             c1 * qvm::A<1,0>(this->m_matrix) + c2 * qvm::A<1,1>(this->m_matrix) + c3 * qvm::A<1,2>(this->m_matrix) + qvm::A<1,3>(this->m_matrix)));
0249 
0250         return true;
0251     }
0252 
0253 };
0254 
0255 
0256 template <typename CalculationType>
0257 class matrix_transformer<CalculationType, 3, 3> : public detail::matrix_transformer::matrix_transformer<CalculationType, 3, 3>
0258 {
0259     typedef CalculationType ct;
0260 public :
0261     template<typename Matrix>
0262     inline matrix_transformer(Matrix const& matrix)
0263     {
0264         qvm::assign(this->m_matrix, matrix);
0265     }
0266 
0267     inline matrix_transformer() {}
0268 
0269     inline matrix_transformer(
0270                 ct const& m_0_0, ct const& m_0_1, ct const& m_0_2, ct const& m_0_3,
0271                 ct const& m_1_0, ct const& m_1_1, ct const& m_1_2, ct const& m_1_3,
0272                 ct const& m_2_0, ct const& m_2_1, ct const& m_2_2, ct const& m_2_3,
0273                 ct const& m_3_0, ct const& m_3_1, ct const& m_3_2, ct const& m_3_3
0274                 )
0275     {
0276         qvm::A<0,0>(this->m_matrix) = m_0_0; qvm::A<0,1>(this->m_matrix) = m_0_1; qvm::A<0,2>(this->m_matrix) = m_0_2; qvm::A<0,3>(this->m_matrix) = m_0_3;
0277         qvm::A<1,0>(this->m_matrix) = m_1_0; qvm::A<1,1>(this->m_matrix) = m_1_1; qvm::A<1,2>(this->m_matrix) = m_1_2; qvm::A<1,3>(this->m_matrix) = m_1_3;
0278         qvm::A<2,0>(this->m_matrix) = m_2_0; qvm::A<2,1>(this->m_matrix) = m_2_1; qvm::A<2,2>(this->m_matrix) = m_2_2; qvm::A<2,3>(this->m_matrix) = m_2_3;
0279         qvm::A<3,0>(this->m_matrix) = m_3_0; qvm::A<3,1>(this->m_matrix) = m_3_1; qvm::A<3,2>(this->m_matrix) = m_3_2; qvm::A<3,3>(this->m_matrix) = m_3_3;
0280     }
0281 
0282     template <typename P1, typename P2>
0283     inline bool apply(P1 const& p1, P2& p2) const
0284     {
0285         assert_dimension_greater_equal<P1, 3>();
0286         assert_dimension_greater_equal<P2, 3>();
0287 
0288         ct const& c1 = get<0>(p1);
0289         ct const& c2 = get<1>(p1);
0290         ct const& c3 = get<2>(p1);
0291 
0292         typedef typename geometry::coordinate_type<P2>::type ct2;
0293 
0294         set<0>(p2, util::numeric_cast<ct2>(
0295             c1 * qvm::A<0,0>(this->m_matrix) + c2 * qvm::A<0,1>(this->m_matrix) + c3 * qvm::A<0,2>(this->m_matrix) + qvm::A<0,3>(this->m_matrix)));
0296         set<1>(p2, util::numeric_cast<ct2>(
0297             c1 * qvm::A<1,0>(this->m_matrix) + c2 * qvm::A<1,1>(this->m_matrix) + c3 * qvm::A<1,2>(this->m_matrix) + qvm::A<1,3>(this->m_matrix)));
0298         set<2>(p2, util::numeric_cast<ct2>(
0299             c1 * qvm::A<2,0>(this->m_matrix) + c2 * qvm::A<2,1>(this->m_matrix) + c3 * qvm::A<2,2>(this->m_matrix) + qvm::A<2,3>(this->m_matrix)));
0300 
0301         return true;
0302     }
0303 };
0304 
0305 
0306 /*!
0307 \brief Strategy of translate transformation in Cartesian system.
0308 \details Translate moves a geometry a fixed distance in 2 or 3 dimensions.
0309 \see http://en.wikipedia.org/wiki/Translation_%28geometry%29
0310 \ingroup strategies
0311 \tparam Dimension1 number of dimensions to transform from
0312 \tparam Dimension2 number of dimensions to transform to
0313  */
0314 template
0315 <
0316     typename CalculationType,
0317     std::size_t Dimension1,
0318     std::size_t Dimension2
0319 >
0320 class translate_transformer
0321 {
0322 };
0323 
0324 
0325 template<typename CalculationType>
0326 class translate_transformer<CalculationType, 2, 2> : public matrix_transformer<CalculationType, 2, 2>
0327 {
0328 public :
0329     // To have translate transformers compatible for 2/3 dimensions, the
0330     // constructor takes an optional third argument doing nothing.
0331     inline translate_transformer(CalculationType const& translate_x,
0332                 CalculationType const& translate_y,
0333                 CalculationType const& = 0)
0334         : matrix_transformer<CalculationType, 2, 2>(
0335                 1, 0, translate_x,
0336                 0, 1, translate_y,
0337                 0, 0, 1)
0338     {}
0339 };
0340 
0341 
0342 template <typename CalculationType>
0343 class translate_transformer<CalculationType, 3, 3> : public matrix_transformer<CalculationType, 3, 3>
0344 {
0345 public :
0346     inline translate_transformer(CalculationType const& translate_x,
0347                 CalculationType const& translate_y,
0348                 CalculationType const& translate_z)
0349         : matrix_transformer<CalculationType, 3, 3>(
0350                 1, 0, 0, translate_x,
0351                 0, 1, 0, translate_y,
0352                 0, 0, 1, translate_z,
0353                 0, 0, 0, 1)
0354     {}
0355 
0356 };
0357 
0358 
0359 /*!
0360 \brief Strategy of scale transformation in Cartesian system.
0361 \details Scale scales a geometry up or down in all its dimensions.
0362 \see http://en.wikipedia.org/wiki/Scaling_%28geometry%29
0363 \ingroup strategies
0364 \tparam Dimension1 number of dimensions to transform from
0365 \tparam Dimension2 number of dimensions to transform to
0366 */
0367 template
0368 <
0369     typename CalculationType,
0370     std::size_t Dimension1,
0371     std::size_t Dimension2
0372 >
0373 class scale_transformer
0374 {
0375 };
0376 
0377 template
0378 <
0379     typename CalculationType,
0380     std::size_t Dimension1
0381 >
0382 class scale_transformer<CalculationType, Dimension1, Dimension1> : public matrix_transformer<CalculationType, Dimension1, Dimension1>
0383 {
0384 public:
0385     inline scale_transformer(CalculationType const& scale)
0386     {
0387         boost::qvm::set_identity(this->m_matrix);
0388         this->m_matrix*=scale;
0389         qvm::A<Dimension1,Dimension1>(this->m_matrix) = 1;
0390     }
0391 };
0392 
0393 template <typename CalculationType>
0394 class scale_transformer<CalculationType, 2, 2> : public matrix_transformer<CalculationType, 2, 2>
0395 {
0396 
0397 public :
0398     inline scale_transformer(CalculationType const& scale_x,
0399                 CalculationType const& scale_y,
0400                 CalculationType const& = 0)
0401         : matrix_transformer<CalculationType, 2, 2>(
0402                 scale_x, 0,       0,
0403                 0,       scale_y, 0,
0404                 0,       0,       1)
0405     {}
0406 
0407 
0408     inline scale_transformer(CalculationType const& scale)
0409         : matrix_transformer<CalculationType, 2, 2>(
0410                 scale, 0,     0,
0411                 0,     scale, 0,
0412                 0,     0,     1)
0413     {}
0414 };
0415 
0416 
0417 template <typename CalculationType>
0418 class scale_transformer<CalculationType, 3, 3> : public matrix_transformer<CalculationType, 3, 3>
0419 {
0420 public :
0421     inline scale_transformer(CalculationType const& scale_x,
0422                 CalculationType const& scale_y,
0423                 CalculationType const& scale_z)
0424         : matrix_transformer<CalculationType, 3, 3>(
0425                 scale_x, 0,       0,       0,
0426                 0,       scale_y, 0,       0,
0427                 0,       0,       scale_z, 0,
0428                 0,       0,       0,       1)
0429     {}
0430 
0431 
0432     inline scale_transformer(CalculationType const& scale)
0433         : matrix_transformer<CalculationType, 3, 3>(
0434                 scale, 0,     0,     0,
0435                 0,     scale, 0,     0,
0436                 0,     0,     scale, 0,
0437                 0,     0,     0,     1)
0438     {}
0439 };
0440 
0441 
0442 #ifndef DOXYGEN_NO_DETAIL
0443 namespace detail
0444 {
0445 
0446 
0447 template <typename DegreeOrRadian>
0448 struct as_radian
0449 {};
0450 
0451 
0452 template <>
0453 struct as_radian<radian>
0454 {
0455     template <typename T>
0456     static inline T get(T const& value)
0457     {
0458         return value;
0459     }
0460 };
0461 
0462 template <>
0463 struct as_radian<degree>
0464 {
0465     template <typename T>
0466     static inline T get(T const& value)
0467     {
0468         typedef typename promote_floating_point<T>::type promoted_type;
0469         return value * math::d2r<promoted_type>();
0470     }
0471 
0472 };
0473 
0474 
0475 template
0476 <
0477     typename CalculationType,
0478     std::size_t Dimension1,
0479     std::size_t Dimension2
0480 >
0481 class rad_rotate_transformer
0482     : public transform::matrix_transformer<CalculationType, Dimension1, Dimension2>
0483 {
0484 public :
0485     inline rad_rotate_transformer(CalculationType const& angle)
0486         : transform::matrix_transformer<CalculationType, Dimension1, Dimension2>(
0487                  cos(angle), sin(angle), 0,
0488                 -sin(angle), cos(angle), 0,
0489                  0,          0,          1)
0490     {}
0491 };
0492 
0493 
0494 } // namespace detail
0495 #endif // DOXYGEN_NO_DETAIL
0496 
0497 
0498 /*!
0499 \brief Strategy for rotate transformation in Cartesian coordinate system.
0500 \details Rotate rotates a geometry by a specified angle about a fixed point (e.g. origin).
0501 \see http://en.wikipedia.org/wiki/Rotation_%28mathematics%29
0502 \ingroup strategies
0503 \tparam DegreeOrRadian degree/or/radian, type of rotation angle specification
0504 \note A single angle is needed to specify a rotation in 2D.
0505       Not yet in 3D, the 3D version requires special things to allow
0506       for rotation around X, Y, Z or arbitrary axis.
0507 \todo The 3D version will not compile.
0508  */
0509 template
0510 <
0511     typename DegreeOrRadian,
0512     typename CalculationType,
0513     std::size_t Dimension1,
0514     std::size_t Dimension2
0515 >
0516 class rotate_transformer : public detail::rad_rotate_transformer<CalculationType, Dimension1, Dimension2>
0517 {
0518 
0519 public :
0520     inline rotate_transformer(CalculationType const& angle)
0521         : detail::rad_rotate_transformer
0522             <
0523                 CalculationType, Dimension1, Dimension2
0524             >(detail::as_radian<DegreeOrRadian>::get(angle))
0525     {}
0526 };
0527 
0528 
0529 }} // namespace strategy::transform
0530 
0531 
0532 }} // namespace boost::geometry
0533 
0534 
0535 #endif // BOOST_GEOMETRY_STRATEGIES_TRANSFORM_MATRIX_TRANSFORMERS_HPP