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_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 }}
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
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
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
0307
0308
0309
0310
0311
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
0329
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
0360
0361
0362
0363
0364
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 }
0494 #endif
0495
0496
0497
0498
0499
0500
0501
0502
0503
0504
0505
0506
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 }}
0529
0530
0531 }}
0532
0533
0534 #endif