Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:36:50

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