]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/geometry/include/boost/geometry/strategies/transform/matrix_transformers.hpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / geometry / include / boost / geometry / strategies / transform / matrix_transformers.hpp
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2
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.
6
7 // This file was modified by Oracle on 2015.
8 // Modifications copyright (c) 2015 Oracle and/or its affiliates.
9
10 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
11
12 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
13 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
14
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)
18
19 #ifndef BOOST_GEOMETRY_STRATEGIES_TRANSFORM_MATRIX_TRANSFORMERS_HPP
20 #define BOOST_GEOMETRY_STRATEGIES_TRANSFORM_MATRIX_TRANSFORMERS_HPP
21
22
23 #include <cstddef>
24
25 // Remove the ublas checking, otherwise the inverse might fail
26 // (while nothing seems to be wrong)
27 #ifdef BOOST_UBLAS_TYPE_CHECK
28 #undef BOOST_UBLAS_TYPE_CHECK
29 #endif
30 #define BOOST_UBLAS_TYPE_CHECK 0
31
32 #include <boost/numeric/conversion/cast.hpp>
33
34 #if defined(__clang__)
35 // Avoid warning about unused UBLAS function: boost_numeric_ublas_abs
36 #pragma clang diagnostic push
37 #pragma clang diagnostic ignored "-Wunused-function"
38 #endif
39
40 #include <boost/numeric/ublas/vector.hpp>
41 #include <boost/numeric/ublas/matrix.hpp>
42
43 #if defined(__clang__)
44 #pragma clang diagnostic pop
45 #endif
46
47 #include <boost/geometry/core/access.hpp>
48 #include <boost/geometry/core/coordinate_dimension.hpp>
49 #include <boost/geometry/core/cs.hpp>
50 #include <boost/geometry/util/math.hpp>
51 #include <boost/geometry/util/promote_floating_point.hpp>
52 #include <boost/geometry/util/select_coordinate_type.hpp>
53 #include <boost/geometry/util/select_most_precise.hpp>
54
55
56 namespace boost { namespace geometry
57 {
58
59 namespace strategy { namespace transform
60 {
61
62 /*!
63 \brief Affine transformation strategy in Cartesian system.
64 \details The strategy serves as a generic definition of affine transformation matrix
65 and procedure of application it to given point.
66 \see http://en.wikipedia.org/wiki/Affine_transformation
67 and http://www.devmaster.net/wiki/Transformation_matrices
68 \ingroup strategies
69 \tparam Dimension1 number of dimensions to transform from
70 \tparam Dimension2 number of dimensions to transform to
71 */
72 template
73 <
74 typename CalculationType,
75 std::size_t Dimension1,
76 std::size_t Dimension2
77 >
78 class ublas_transformer
79 {
80 };
81
82
83 template <typename CalculationType>
84 class ublas_transformer<CalculationType, 2, 2>
85 {
86 protected :
87 typedef CalculationType ct;
88 typedef boost::numeric::ublas::matrix<ct> matrix_type;
89 matrix_type m_matrix;
90
91 public :
92
93 inline ublas_transformer(
94 ct const& m_0_0, ct const& m_0_1, ct const& m_0_2,
95 ct const& m_1_0, ct const& m_1_1, ct const& m_1_2,
96 ct const& m_2_0, ct const& m_2_1, ct const& m_2_2)
97 : m_matrix(3, 3)
98 {
99 m_matrix(0,0) = m_0_0; m_matrix(0,1) = m_0_1; m_matrix(0,2) = m_0_2;
100 m_matrix(1,0) = m_1_0; m_matrix(1,1) = m_1_1; m_matrix(1,2) = m_1_2;
101 m_matrix(2,0) = m_2_0; m_matrix(2,1) = m_2_1; m_matrix(2,2) = m_2_2;
102 }
103
104 inline ublas_transformer(matrix_type const& matrix)
105 : m_matrix(matrix)
106 {}
107
108
109 inline ublas_transformer() : m_matrix(3, 3) {}
110
111 template <typename P1, typename P2>
112 inline bool apply(P1 const& p1, P2& p2) const
113 {
114 assert_dimension_greater_equal<P1, 2>();
115 assert_dimension_greater_equal<P2, 2>();
116
117 ct const& c1 = get<0>(p1);
118 ct const& c2 = get<1>(p1);
119
120 ct p2x = c1 * m_matrix(0,0) + c2 * m_matrix(0,1) + m_matrix(0,2);
121 ct p2y = c1 * m_matrix(1,0) + c2 * m_matrix(1,1) + m_matrix(1,2);
122
123 typedef typename geometry::coordinate_type<P2>::type ct2;
124 set<0>(p2, boost::numeric_cast<ct2>(p2x));
125 set<1>(p2, boost::numeric_cast<ct2>(p2y));
126
127 return true;
128 }
129
130 matrix_type const& matrix() const { return m_matrix; }
131 };
132
133
134 // It IS possible to go from 3 to 2 coordinates
135 template <typename CalculationType>
136 class ublas_transformer<CalculationType, 3, 2> : public ublas_transformer<CalculationType, 2, 2>
137 {
138 typedef CalculationType ct;
139
140 public :
141 inline ublas_transformer(
142 ct const& m_0_0, ct const& m_0_1, ct const& m_0_2,
143 ct const& m_1_0, ct const& m_1_1, ct const& m_1_2,
144 ct const& m_2_0, ct const& m_2_1, ct const& m_2_2)
145 : ublas_transformer<CalculationType, 2, 2>(
146 m_0_0, m_0_1, m_0_2,
147 m_1_0, m_1_1, m_1_2,
148 m_2_0, m_2_1, m_2_2)
149 {}
150
151 inline ublas_transformer()
152 : ublas_transformer<CalculationType, 2, 2>()
153 {}
154 };
155
156
157 template <typename CalculationType>
158 class ublas_transformer<CalculationType, 3, 3>
159 {
160 protected :
161 typedef CalculationType ct;
162 typedef boost::numeric::ublas::matrix<ct> matrix_type;
163 matrix_type m_matrix;
164
165 public :
166 inline ublas_transformer(
167 ct const& m_0_0, ct const& m_0_1, ct const& m_0_2, ct const& m_0_3,
168 ct const& m_1_0, ct const& m_1_1, ct const& m_1_2, ct const& m_1_3,
169 ct const& m_2_0, ct const& m_2_1, ct const& m_2_2, ct const& m_2_3,
170 ct const& m_3_0, ct const& m_3_1, ct const& m_3_2, ct const& m_3_3
171 )
172 : m_matrix(4, 4)
173 {
174 m_matrix(0,0) = m_0_0; m_matrix(0,1) = m_0_1; m_matrix(0,2) = m_0_2; m_matrix(0,3) = m_0_3;
175 m_matrix(1,0) = m_1_0; m_matrix(1,1) = m_1_1; m_matrix(1,2) = m_1_2; m_matrix(1,3) = m_1_3;
176 m_matrix(2,0) = m_2_0; m_matrix(2,1) = m_2_1; m_matrix(2,2) = m_2_2; m_matrix(2,3) = m_2_3;
177 m_matrix(3,0) = m_3_0; m_matrix(3,1) = m_3_1; m_matrix(3,2) = m_3_2; m_matrix(3,3) = m_3_3;
178 }
179
180 inline ublas_transformer() : m_matrix(4, 4) {}
181
182 template <typename P1, typename P2>
183 inline bool apply(P1 const& p1, P2& p2) const
184 {
185 ct const& c1 = get<0>(p1);
186 ct const& c2 = get<1>(p1);
187 ct const& c3 = get<2>(p1);
188
189 typedef typename geometry::coordinate_type<P2>::type ct2;
190
191 set<0>(p2, boost::numeric_cast<ct2>(
192 c1 * m_matrix(0,0) + c2 * m_matrix(0,1) + c3 * m_matrix(0,2) + m_matrix(0,3)));
193 set<1>(p2, boost::numeric_cast<ct2>(
194 c1 * m_matrix(1,0) + c2 * m_matrix(1,1) + c3 * m_matrix(1,2) + m_matrix(1,3)));
195 set<2>(p2, boost::numeric_cast<ct2>(
196 c1 * m_matrix(2,0) + c2 * m_matrix(2,1) + c3 * m_matrix(2,2) + m_matrix(2,3)));
197
198 return true;
199 }
200
201 matrix_type const& matrix() const { return m_matrix; }
202 };
203
204
205 /*!
206 \brief Strategy of translate transformation in Cartesian system.
207 \details Translate moves a geometry a fixed distance in 2 or 3 dimensions.
208 \see http://en.wikipedia.org/wiki/Translation_%28geometry%29
209 \ingroup strategies
210 \tparam Dimension1 number of dimensions to transform from
211 \tparam Dimension2 number of dimensions to transform to
212 */
213 template
214 <
215 typename CalculationType,
216 std::size_t Dimension1,
217 std::size_t Dimension2
218 >
219 class translate_transformer
220 {
221 };
222
223
224 template<typename CalculationType>
225 class translate_transformer<CalculationType, 2, 2> : public ublas_transformer<CalculationType, 2, 2>
226 {
227 public :
228 // To have translate transformers compatible for 2/3 dimensions, the
229 // constructor takes an optional third argument doing nothing.
230 inline translate_transformer(CalculationType const& translate_x,
231 CalculationType const& translate_y,
232 CalculationType const& = 0)
233 : ublas_transformer<CalculationType, 2, 2>(
234 1, 0, translate_x,
235 0, 1, translate_y,
236 0, 0, 1)
237 {}
238 };
239
240
241 template <typename CalculationType>
242 class translate_transformer<CalculationType, 3, 3> : public ublas_transformer<CalculationType, 3, 3>
243 {
244 public :
245 inline translate_transformer(CalculationType const& translate_x,
246 CalculationType const& translate_y,
247 CalculationType const& translate_z)
248 : ublas_transformer<CalculationType, 3, 3>(
249 1, 0, 0, translate_x,
250 0, 1, 0, translate_y,
251 0, 0, 1, translate_z,
252 0, 0, 0, 1)
253 {}
254
255 };
256
257
258 /*!
259 \brief Strategy of scale transformation in Cartesian system.
260 \details Scale scales a geometry up or down in all its dimensions.
261 \see http://en.wikipedia.org/wiki/Scaling_%28geometry%29
262 \ingroup strategies
263 \tparam Dimension1 number of dimensions to transform from
264 \tparam Dimension2 number of dimensions to transform to
265 */
266 template
267 <
268 typename CalculationType,
269 std::size_t Dimension1,
270 std::size_t Dimension2
271 >
272 class scale_transformer
273 {
274 };
275
276
277 template <typename CalculationType>
278 class scale_transformer<CalculationType, 2, 2> : public ublas_transformer<CalculationType, 2, 2>
279 {
280
281 public :
282 inline scale_transformer(CalculationType const& scale_x,
283 CalculationType const& scale_y,
284 CalculationType const& = 0)
285 : ublas_transformer<CalculationType, 2, 2>(
286 scale_x, 0, 0,
287 0, scale_y, 0,
288 0, 0, 1)
289 {}
290
291
292 inline scale_transformer(CalculationType const& scale)
293 : ublas_transformer<CalculationType, 2, 2>(
294 scale, 0, 0,
295 0, scale, 0,
296 0, 0, 1)
297 {}
298 };
299
300
301 template <typename CalculationType>
302 class scale_transformer<CalculationType, 3, 3> : public ublas_transformer<CalculationType, 3, 3>
303 {
304 public :
305 inline scale_transformer(CalculationType const& scale_x,
306 CalculationType const& scale_y,
307 CalculationType const& scale_z)
308 : ublas_transformer<CalculationType, 3, 3>(
309 scale_x, 0, 0, 0,
310 0, scale_y, 0, 0,
311 0, 0, scale_z, 0,
312 0, 0, 0, 1)
313 {}
314
315
316 inline scale_transformer(CalculationType const& scale)
317 : ublas_transformer<CalculationType, 3, 3>(
318 scale, 0, 0, 0,
319 0, scale, 0, 0,
320 0, 0, scale, 0,
321 0, 0, 0, 1)
322 {}
323 };
324
325
326 #ifndef DOXYGEN_NO_DETAIL
327 namespace detail
328 {
329
330
331 template <typename DegreeOrRadian>
332 struct as_radian
333 {};
334
335
336 template <>
337 struct as_radian<radian>
338 {
339 template <typename T>
340 static inline T get(T const& value)
341 {
342 return value;
343 }
344 };
345
346 template <>
347 struct as_radian<degree>
348 {
349 template <typename T>
350 static inline T get(T const& value)
351 {
352 typedef typename promote_floating_point<T>::type promoted_type;
353 return value * math::d2r<promoted_type>();
354 }
355
356 };
357
358
359 template
360 <
361 typename CalculationType,
362 std::size_t Dimension1,
363 std::size_t Dimension2
364 >
365 class rad_rotate_transformer
366 : public ublas_transformer<CalculationType, Dimension1, Dimension2>
367 {
368 public :
369 inline rad_rotate_transformer(CalculationType const& angle)
370 : ublas_transformer<CalculationType, Dimension1, Dimension2>(
371 cos(angle), sin(angle), 0,
372 -sin(angle), cos(angle), 0,
373 0, 0, 1)
374 {}
375 };
376
377
378 } // namespace detail
379 #endif // DOXYGEN_NO_DETAIL
380
381
382 /*!
383 \brief Strategy for rotate transformation in Cartesian coordinate system.
384 \details Rotate rotates a geometry of specified angle about a fixed point (e.g. origin).
385 \see http://en.wikipedia.org/wiki/Rotation_%28mathematics%29
386 \ingroup strategies
387 \tparam DegreeOrRadian degree/or/radian, type of rotation angle specification
388 \note A single angle is needed to specify a rotation in 2D.
389 Not yet in 3D, the 3D version requires special things to allow
390 for rotation around X, Y, Z or arbitrary axis.
391 \todo The 3D version will not compile.
392 */
393 template
394 <
395 typename DegreeOrRadian,
396 typename CalculationType,
397 std::size_t Dimension1,
398 std::size_t Dimension2
399 >
400 class rotate_transformer : public detail::rad_rotate_transformer<CalculationType, Dimension1, Dimension2>
401 {
402
403 public :
404 inline rotate_transformer(CalculationType const& angle)
405 : detail::rad_rotate_transformer
406 <
407 CalculationType, Dimension1, Dimension2
408 >(detail::as_radian<DegreeOrRadian>::get(angle))
409 {}
410 };
411
412
413 }} // namespace strategy::transform
414
415
416 }} // namespace boost::geometry
417
418
419 #endif // BOOST_GEOMETRY_STRATEGIES_TRANSFORM_MATRIX_TRANSFORMERS_HPP