]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 ublas_transformer<CalculationType, Dimension1, Dimension2> | |
50 | { | |
51 | typedef boost::numeric::ublas::matrix<CalculationType> M; | |
52 | ||
53 | public : | |
54 | template <typename B, typename D> | |
55 | explicit inline map_transformer(B const& box, D const& width, D const& height) | |
56 | { | |
57 | set_transformation( | |
58 | get<min_corner, 0>(box), get<min_corner, 1>(box), | |
59 | get<max_corner, 0>(box), get<max_corner, 1>(box), | |
60 | width, height); | |
61 | } | |
62 | ||
63 | template <typename W, typename D> | |
64 | explicit inline map_transformer(W const& wx1, W const& wy1, W const& wx2, W const& wy2, | |
65 | D const& width, D const& height) | |
66 | { | |
67 | set_transformation(wx1, wy1, wx2, wy2, width, height); | |
68 | } | |
69 | ||
70 | ||
71 | private : | |
72 | template <typename W, typename P, typename S> | |
73 | inline void set_transformation_point(W const& wx, W const& wy, | |
74 | P const& px, P const& py, | |
75 | S const& scalex, S const& scaley) | |
76 | { | |
77 | ||
78 | // Translate to a coordinate system centered on world coordinates (-wx, -wy) | |
79 | M t1(3,3); | |
80 | t1(0,0) = 1; t1(0,1) = 0; t1(0,2) = -wx; | |
81 | t1(1,0) = 0; t1(1,1) = 1; t1(1,2) = -wy; | |
82 | t1(2,0) = 0; t1(2,1) = 0; t1(2,2) = 1; | |
83 | ||
84 | // Scale the map | |
85 | M s(3,3); | |
86 | s(0,0) = scalex; s(0,1) = 0; s(0,2) = 0; | |
87 | s(1,0) = 0; s(1,1) = scaley; s(1,2) = 0; | |
88 | s(2,0) = 0; s(2,1) = 0; s(2,2) = 1; | |
89 | ||
90 | // Translate to a coordinate system centered on the specified pixels (+px, +py) | |
91 | M t2(3, 3); | |
92 | t2(0,0) = 1; t2(0,1) = 0; t2(0,2) = px; | |
93 | t2(1,0) = 0; t2(1,1) = 1; t2(1,2) = py; | |
94 | t2(2,0) = 0; t2(2,1) = 0; t2(2,2) = 1; | |
95 | ||
96 | // Calculate combination matrix in two steps | |
97 | this->m_matrix = boost::numeric::ublas::prod(s, t1); | |
98 | this->m_matrix = boost::numeric::ublas::prod(t2, this->m_matrix); | |
99 | } | |
100 | ||
101 | ||
102 | template <typename W, typename D> | |
103 | void set_transformation(W const& wx1, W const& wy1, W const& wx2, W const& wy2, | |
104 | D const& width, D const& height) | |
105 | { | |
106 | D px1 = 0; | |
107 | D py1 = 0; | |
108 | D px2 = width; | |
109 | D py2 = height; | |
110 | ||
111 | // Get the same type, but at least a double | |
112 | typedef typename select_most_precise<D, double>::type type; | |
113 | ||
114 | ||
115 | // Calculate appropriate scale, take min because whole box must fit | |
116 | // Scale is in PIXELS/MAPUNITS (meters) | |
117 | W wdx = wx2 - wx1; | |
118 | W wdy = wy2 - wy1; | |
119 | type sx = (px2 - px1) / boost::numeric_cast<type>(wdx); | |
120 | type sy = (py2 - py1) / boost::numeric_cast<type>(wdy); | |
121 | ||
122 | if (SameScale) | |
123 | { | |
124 | type scale = (std::min)(sx, sy); | |
125 | sx = scale; | |
126 | sy = scale; | |
127 | } | |
128 | ||
129 | // Calculate centerpoints | |
130 | W wtx = wx1 + wx2; | |
131 | W wty = wy1 + wy2; | |
132 | W two = 2; | |
133 | W wmx = wtx / two; | |
134 | W wmy = wty / two; | |
135 | type pmx = (px1 + px2) / 2.0; | |
136 | type pmy = (py1 + py2) / 2.0; | |
137 | ||
138 | set_transformation_point(wmx, wmy, pmx, pmy, sx, sy); | |
139 | ||
140 | if (Mirror) | |
141 | { | |
142 | // Mirror in y-direction | |
143 | M m(3,3); | |
144 | m(0,0) = 1; m(0,1) = 0; m(0,2) = 0; | |
145 | m(1,0) = 0; m(1,1) = -1; m(1,2) = 0; | |
146 | m(2,0) = 0; m(2,1) = 0; m(2,2) = 1; | |
147 | ||
148 | // Translate in y-direction such that it fits again | |
149 | M y(3, 3); | |
150 | y(0,0) = 1; y(0,1) = 0; y(0,2) = 0; | |
151 | y(1,0) = 0; y(1,1) = 1; y(1,2) = height; | |
152 | y(2,0) = 0; y(2,1) = 0; y(2,2) = 1; | |
153 | ||
154 | // Calculate combination matrix in two steps | |
155 | this->m_matrix = boost::numeric::ublas::prod(m, this->m_matrix); | |
156 | this->m_matrix = boost::numeric::ublas::prod(y, this->m_matrix); | |
157 | } | |
158 | } | |
159 | }; | |
160 | ||
161 | ||
162 | }} // namespace strategy::transform | |
163 | ||
164 | #if defined(_MSC_VER) | |
165 | #pragma warning(pop) | |
166 | #endif | |
167 | ||
168 | }} // namespace boost::geometry | |
169 | ||
170 | ||
171 | #endif // BOOST_GEOMETRY_STRATEGIES_TRANSFORM_MAP_TRANSFORMER_HPP |