]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 |