File indexing completed on 2025-07-11 08:12:23
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
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 }}
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
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
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
0308
0309
0310
0311
0312
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
0330
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
0361
0362
0363
0364
0365
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 }
0495 #endif
0496
0497
0498
0499
0500
0501
0502
0503
0504
0505
0506
0507
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 }}
0530
0531
0532 }}
0533
0534
0535 #endif