1 // Boost.Geometry (aka GGL, Generic Geometry Library)
3 // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
4 // Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
5 // Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
7 // This file was modified by Oracle on 2015.
8 // Modifications copyright (c) 2015 Oracle and/or its affiliates.
10 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
12 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
13 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
15 // Use, modification and distribution is subject to the Boost Software License,
16 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
17 // http://www.boost.org/LICENSE_1_0.txt)
19 #ifndef BOOST_GEOMETRY_STRATEGIES_TRANSFORM_MATRIX_TRANSFORMERS_HPP
20 #define BOOST_GEOMETRY_STRATEGIES_TRANSFORM_MATRIX_TRANSFORMERS_HPP
25 #include <boost/qvm/mat.hpp>
26 #include <boost/qvm/mat_access.hpp>
27 #include <boost/qvm/mat_operations.hpp>
29 #include <boost/geometry/core/access.hpp>
30 #include <boost/geometry/core/coordinate_dimension.hpp>
31 #include <boost/geometry/core/cs.hpp>
32 #include <boost/geometry/util/math.hpp>
33 #include <boost/geometry/util/promote_floating_point.hpp>
34 #include <boost/geometry/util/select_coordinate_type.hpp>
35 #include <boost/geometry/util/select_most_precise.hpp>
38 namespace boost { namespace geometry
41 namespace strategy { namespace transform
45 \brief Affine transformation strategy in Cartesian system.
46 \details The strategy serves as a generic definition of affine transformation matrix
47 and procedure of application it to given point.
48 \see http://en.wikipedia.org/wiki/Affine_transformation
49 and http://www.devmaster.net/wiki/Transformation_matrices
51 \tparam Dimension1 number of dimensions to transform from
52 \tparam Dimension2 number of dimensions to transform to
56 typename CalculationType,
57 std::size_t Dimension1,
58 std::size_t Dimension2
60 class matrix_transformer
65 template <typename CalculationType>
66 class matrix_transformer<CalculationType, 2, 2>
69 typedef CalculationType ct;
70 typedef boost::qvm::mat<ct, 3, 3> matrix_type;
75 inline matrix_transformer(
76 ct const& m_0_0, ct const& m_0_1, ct const& m_0_2,
77 ct const& m_1_0, ct const& m_1_1, ct const& m_1_2,
78 ct const& m_2_0, ct const& m_2_1, ct const& m_2_2)
80 qvm::A<0,0>(m_matrix) = m_0_0; qvm::A<0,1>(m_matrix) = m_0_1; qvm::A<0,2>(m_matrix) = m_0_2;
81 qvm::A<1,0>(m_matrix) = m_1_0; qvm::A<1,1>(m_matrix) = m_1_1; qvm::A<1,2>(m_matrix) = m_1_2;
82 qvm::A<2,0>(m_matrix) = m_2_0; qvm::A<2,1>(m_matrix) = m_2_1; qvm::A<2,2>(m_matrix) = m_2_2;
85 inline matrix_transformer(matrix_type const& matrix)
90 inline matrix_transformer() {}
92 template <typename P1, typename P2>
93 inline bool apply(P1 const& p1, P2& p2) const
95 assert_dimension_greater_equal<P1, 2>();
96 assert_dimension_greater_equal<P2, 2>();
98 ct const& c1 = get<0>(p1);
99 ct const& c2 = get<1>(p1);
101 ct p2x = c1 * qvm::A<0,0>(m_matrix) + c2 * qvm::A<0,1>(m_matrix) + qvm::A<0,2>(m_matrix);
102 ct p2y = c1 * qvm::A<1,0>(m_matrix) + c2 * qvm::A<1,1>(m_matrix) + qvm::A<1,2>(m_matrix);
104 typedef typename geometry::coordinate_type<P2>::type ct2;
105 set<0>(p2, boost::numeric_cast<ct2>(p2x));
106 set<1>(p2, boost::numeric_cast<ct2>(p2y));
111 matrix_type const& matrix() const { return m_matrix; }
115 // It IS possible to go from 3 to 2 coordinates
116 template <typename CalculationType>
117 class matrix_transformer<CalculationType, 3, 2> : public matrix_transformer<CalculationType, 2, 2>
119 typedef CalculationType ct;
122 inline matrix_transformer(
123 ct const& m_0_0, ct const& m_0_1, ct const& m_0_2,
124 ct const& m_1_0, ct const& m_1_1, ct const& m_1_2,
125 ct const& m_2_0, ct const& m_2_1, ct const& m_2_2)
126 : matrix_transformer<CalculationType, 2, 2>(
132 inline matrix_transformer()
133 : matrix_transformer<CalculationType, 2, 2>()
138 template <typename CalculationType>
139 class matrix_transformer<CalculationType, 3, 3>
142 typedef CalculationType ct;
143 typedef boost::qvm::mat<ct, 4, 4> matrix_type;
144 matrix_type m_matrix;
147 inline matrix_transformer(
148 ct const& m_0_0, ct const& m_0_1, ct const& m_0_2, ct const& m_0_3,
149 ct const& m_1_0, ct const& m_1_1, ct const& m_1_2, ct const& m_1_3,
150 ct const& m_2_0, ct const& m_2_1, ct const& m_2_2, ct const& m_2_3,
151 ct const& m_3_0, ct const& m_3_1, ct const& m_3_2, ct const& m_3_3
154 qvm::A<0,0>(m_matrix) = m_0_0; qvm::A<0,1>(m_matrix) = m_0_1; qvm::A<0,2>(m_matrix) = m_0_2; qvm::A<0,3>(m_matrix) = m_0_3;
155 qvm::A<1,0>(m_matrix) = m_1_0; qvm::A<1,1>(m_matrix) = m_1_1; qvm::A<1,2>(m_matrix) = m_1_2; qvm::A<1,3>(m_matrix) = m_1_3;
156 qvm::A<2,0>(m_matrix) = m_2_0; qvm::A<2,1>(m_matrix) = m_2_1; qvm::A<2,2>(m_matrix) = m_2_2; qvm::A<2,3>(m_matrix) = m_2_3;
157 qvm::A<3,0>(m_matrix) = m_3_0; qvm::A<3,1>(m_matrix) = m_3_1; qvm::A<3,2>(m_matrix) = m_3_2; qvm::A<3,3>(m_matrix) = m_3_3;
160 inline matrix_transformer() {}
162 template <typename P1, typename P2>
163 inline bool apply(P1 const& p1, P2& p2) const
165 ct const& c1 = get<0>(p1);
166 ct const& c2 = get<1>(p1);
167 ct const& c3 = get<2>(p1);
169 typedef typename geometry::coordinate_type<P2>::type ct2;
171 set<0>(p2, boost::numeric_cast<ct2>(
172 c1 * m_matrix(0,0) + c2 * m_matrix(0,1) + c3 * m_matrix(0,2) + m_matrix(0,3)));
173 set<1>(p2, boost::numeric_cast<ct2>(
174 c1 * m_matrix(1,0) + c2 * m_matrix(1,1) + c3 * m_matrix(1,2) + m_matrix(1,3)));
175 set<2>(p2, boost::numeric_cast<ct2>(
176 c1 * m_matrix(2,0) + c2 * m_matrix(2,1) + c3 * m_matrix(2,2) + m_matrix(2,3)));
181 matrix_type const& matrix() const { return m_matrix; }
186 \brief Strategy of translate transformation in Cartesian system.
187 \details Translate moves a geometry a fixed distance in 2 or 3 dimensions.
188 \see http://en.wikipedia.org/wiki/Translation_%28geometry%29
190 \tparam Dimension1 number of dimensions to transform from
191 \tparam Dimension2 number of dimensions to transform to
195 typename CalculationType,
196 std::size_t Dimension1,
197 std::size_t Dimension2
199 class translate_transformer
204 template<typename CalculationType>
205 class translate_transformer<CalculationType, 2, 2> : public matrix_transformer<CalculationType, 2, 2>
208 // To have translate transformers compatible for 2/3 dimensions, the
209 // constructor takes an optional third argument doing nothing.
210 inline translate_transformer(CalculationType const& translate_x,
211 CalculationType const& translate_y,
212 CalculationType const& = 0)
213 : matrix_transformer<CalculationType, 2, 2>(
221 template <typename CalculationType>
222 class translate_transformer<CalculationType, 3, 3> : public matrix_transformer<CalculationType, 3, 3>
225 inline translate_transformer(CalculationType const& translate_x,
226 CalculationType const& translate_y,
227 CalculationType const& translate_z)
228 : matrix_transformer<CalculationType, 3, 3>(
229 1, 0, 0, translate_x,
230 0, 1, 0, translate_y,
231 0, 0, 1, translate_z,
239 \brief Strategy of scale transformation in Cartesian system.
240 \details Scale scales a geometry up or down in all its dimensions.
241 \see http://en.wikipedia.org/wiki/Scaling_%28geometry%29
243 \tparam Dimension1 number of dimensions to transform from
244 \tparam Dimension2 number of dimensions to transform to
248 typename CalculationType,
249 std::size_t Dimension1,
250 std::size_t Dimension2
252 class scale_transformer
257 template <typename CalculationType>
258 class scale_transformer<CalculationType, 2, 2> : public matrix_transformer<CalculationType, 2, 2>
262 inline scale_transformer(CalculationType const& scale_x,
263 CalculationType const& scale_y,
264 CalculationType const& = 0)
265 : matrix_transformer<CalculationType, 2, 2>(
272 inline scale_transformer(CalculationType const& scale)
273 : matrix_transformer<CalculationType, 2, 2>(
281 template <typename CalculationType>
282 class scale_transformer<CalculationType, 3, 3> : public matrix_transformer<CalculationType, 3, 3>
285 inline scale_transformer(CalculationType const& scale_x,
286 CalculationType const& scale_y,
287 CalculationType const& scale_z)
288 : matrix_transformer<CalculationType, 3, 3>(
296 inline scale_transformer(CalculationType const& scale)
297 : matrix_transformer<CalculationType, 3, 3>(
306 #ifndef DOXYGEN_NO_DETAIL
311 template <typename DegreeOrRadian>
317 struct as_radian<radian>
319 template <typename T>
320 static inline T get(T const& value)
327 struct as_radian<degree>
329 template <typename T>
330 static inline T get(T const& value)
332 typedef typename promote_floating_point<T>::type promoted_type;
333 return value * math::d2r<promoted_type>();
341 typename CalculationType,
342 std::size_t Dimension1,
343 std::size_t Dimension2
345 class rad_rotate_transformer
346 : public matrix_transformer<CalculationType, Dimension1, Dimension2>
349 inline rad_rotate_transformer(CalculationType const& angle)
350 : matrix_transformer<CalculationType, Dimension1, Dimension2>(
351 cos(angle), sin(angle), 0,
352 -sin(angle), cos(angle), 0,
358 } // namespace detail
359 #endif // DOXYGEN_NO_DETAIL
363 \brief Strategy for rotate transformation in Cartesian coordinate system.
364 \details Rotate rotates a geometry of specified angle about a fixed point (e.g. origin).
365 \see http://en.wikipedia.org/wiki/Rotation_%28mathematics%29
367 \tparam DegreeOrRadian degree/or/radian, type of rotation angle specification
368 \note A single angle is needed to specify a rotation in 2D.
369 Not yet in 3D, the 3D version requires special things to allow
370 for rotation around X, Y, Z or arbitrary axis.
371 \todo The 3D version will not compile.
375 typename DegreeOrRadian,
376 typename CalculationType,
377 std::size_t Dimension1,
378 std::size_t Dimension2
380 class rotate_transformer : public detail::rad_rotate_transformer<CalculationType, Dimension1, Dimension2>
384 inline rotate_transformer(CalculationType const& angle)
385 : detail::rad_rotate_transformer
387 CalculationType, Dimension1, Dimension2
388 >(detail::as_radian<DegreeOrRadian>::get(angle))
393 }} // namespace strategy::transform
396 }} // namespace boost::geometry
399 #endif // BOOST_GEOMETRY_STRATEGIES_TRANSFORM_MATRIX_TRANSFORMERS_HPP