map_transformer.hpp 5.6 KB

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