Imported Upstream version 1.64.0
[platform/upstream/boost.git] / boost / geometry / strategies / transform / map_transformer.hpp
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2
3 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
4 // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
5 // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
6
7 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
8 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
9
10 // Use, modification and distribution is subject to the Boost Software License,
11 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
12 // http://www.boost.org/LICENSE_1_0.txt)
13
14 #ifndef BOOST_GEOMETRY_STRATEGIES_TRANSFORM_MAP_TRANSFORMER_HPP
15 #define BOOST_GEOMETRY_STRATEGIES_TRANSFORM_MAP_TRANSFORMER_HPP
16
17
18 #include <cstddef>
19
20 #include <boost/geometry/strategies/transform/matrix_transformers.hpp>
21
22 namespace boost { namespace geometry
23 {
24
25 // Silence warning C4127: conditional expression is constant
26 #if defined(_MSC_VER)
27 #pragma warning(push)
28 #pragma warning(disable : 4127)
29 #endif
30
31 namespace strategy { namespace transform
32 {
33
34 /*!
35 \brief Transformation strategy to map from one to another Cartesian coordinate system
36 \ingroup strategies
37 \tparam Mirror if true map is mirrored upside-down (in most cases pixels
38     are from top to bottom, while map is from bottom to top)
39  */
40 template
41 <
42     typename CalculationType,
43     std::size_t Dimension1,
44     std::size_t Dimension2,
45     bool Mirror = false,
46     bool SameScale = true
47 >
48 class map_transformer
49     : public matrix_transformer<CalculationType, Dimension1, Dimension2>
50 {
51     typedef boost::qvm::mat<CalculationType, Dimension1 + 1, Dimension2 + 1> M;
52     typedef boost::qvm::mat<CalculationType, 3, 3> matrix33;
53
54 public :
55     template <typename B, typename D>
56     explicit inline map_transformer(B const& box, D const& width, D const& height)
57     {
58         set_transformation(
59                 get<min_corner, 0>(box), get<min_corner, 1>(box),
60                 get<max_corner, 0>(box), get<max_corner, 1>(box),
61                 width, height);
62     }
63
64     template <typename W, typename D>
65     explicit inline map_transformer(W const& wx1, W const& wy1, W const& wx2, W const& wy2,
66                         D const& width, D const& height)
67     {
68         set_transformation(wx1, wy1, wx2, wy2, width, height);
69     }
70
71
72 private :
73     template <typename W, typename P, typename S>
74     inline void set_transformation_point(W const& wx, W const& wy,
75         P const& px, P const& py,
76         S const& scalex, S const& scaley)
77     {
78
79         // Translate to a coordinate system centered on world coordinates (-wx, -wy)
80         matrix33 t1;
81         qvm::A<0,0>(t1) = 1;   qvm::A<0,1>(t1) = 0;   qvm::A<0,2>(t1) = -wx;
82         qvm::A<1,0>(t1) = 0;   qvm::A<1,1>(t1) = 1;   qvm::A<1,2>(t1) = -wy;
83         qvm::A<2,0>(t1) = 0;   qvm::A<2,1>(t1) = 0;   qvm::A<2,2>(t1) = 1;
84
85         // Scale the map
86         matrix33 s;
87         qvm::A<0,0>(s) = scalex;   qvm::A<0,1>(s) = 0;      qvm::A<0,2>(s) = 0;
88         qvm::A<1,0>(s) = 0;        qvm::A<1,1>(s) = scaley; qvm::A<1,2>(s) = 0;
89         qvm::A<2,0>(s) = 0;        qvm::A<2,1>(s) = 0;      qvm::A<2,2>(s) = 1;
90
91         // Translate to a coordinate system centered on the specified pixels (+px, +py)
92         matrix33 t2;
93         qvm::A<0,0>(t2) = 1;   qvm::A<0,1>(t2) = 0;   qvm::A<0,2>(t2) = px;
94         qvm::A<1,0>(t2) = 0;   qvm::A<1,1>(t2) = 1;   qvm::A<1,2>(t2) = py;
95         qvm::A<2,0>(t2) = 0;   qvm::A<2,1>(t2) = 0;   qvm::A<2,2>(t2) = 1;
96
97         // Calculate combination matrix in two steps
98         this->m_matrix = s * t1;
99         this->m_matrix = t2 * this->m_matrix;
100     }
101
102
103     template <typename W, typename D>
104     void set_transformation(W const& wx1, W const& wy1, W const& wx2, W const& wy2,
105                     D const& width, D const& height)
106     {
107         D px1 = 0;
108         D py1 = 0;
109         D px2 = width;
110         D py2 = height;
111
112         // Get the same type, but at least a double
113         typedef typename select_most_precise<D, double>::type type;
114
115
116         // Calculate appropriate scale, take min because whole box must fit
117         // Scale is in PIXELS/MAPUNITS (meters)
118         W wdx = wx2 - wx1;
119         W wdy = wy2 - wy1;
120         type sx = (px2 - px1) / boost::numeric_cast<type>(wdx);
121         type sy = (py2 - py1) / boost::numeric_cast<type>(wdy);
122
123         if (SameScale)
124         {
125             type scale = (std::min)(sx, sy);
126             sx = scale;
127             sy = scale;
128         }
129
130         // Calculate centerpoints
131         W wtx = wx1 + wx2;
132         W wty = wy1 + wy2;
133         W two = 2;
134         W wmx = wtx / two;
135         W wmy = wty / two;
136         type pmx = (px1 + px2) / 2.0;
137         type pmy = (py1 + py2) / 2.0;
138
139         set_transformation_point(wmx, wmy, pmx, pmy, sx, sy);
140
141         if (Mirror)
142         {
143             // Mirror in y-direction
144             matrix33 m;
145             qvm::A<0,0>(m) = 1;   qvm::A<0,1>(m) = 0;   qvm::A<0,2>(m) = 0;
146             qvm::A<1,0>(m) = 0;   qvm::A<1,1>(m) = -1;  qvm::A<1,2>(m) = 0;
147             qvm::A<2,0>(m) = 0;   qvm::A<2,1>(m) = 0;   qvm::A<2,2>(m) = 1;
148
149             // Translate in y-direction such that it fits again
150             matrix33 y;
151             qvm::A<0,0>(y) = 1;   qvm::A<0,1>(y) = 0;   qvm::A<0,2>(y) = 0;
152             qvm::A<1,0>(y) = 0;   qvm::A<1,1>(y) = 1;   qvm::A<1,2>(y) = height;
153             qvm::A<2,0>(y) = 0;   qvm::A<2,1>(y) = 0;   qvm::A<2,2>(y) = 1;
154
155             // Calculate combination matrix in two steps
156             this->m_matrix = m * this->m_matrix;
157             this->m_matrix = y * this->m_matrix;
158         }
159     }
160 };
161
162
163 }} // namespace strategy::transform
164
165 #if defined(_MSC_VER)
166 #pragma warning(pop)
167 #endif
168
169 }} // namespace boost::geometry
170
171
172 #endif // BOOST_GEOMETRY_STRATEGIES_TRANSFORM_MAP_TRANSFORMER_HPP