06_b_transformation_example.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Example: Affine Transformation (translate, scale, rotate)
  3. //
  4. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
  5. //
  6. // Use, modification and distribution is subject to the Boost Software License,
  7. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  8. // http://www.boost.org/LICENSE_1_0.txt)
  9. #include <ctime> // for std::time
  10. #include <algorithm>
  11. #include <fstream>
  12. #include <iostream>
  13. #include <limits>
  14. #include <sstream>
  15. #include <boost/geometry/geometry.hpp>
  16. #include <boost/geometry/geometries/point_xy.hpp>
  17. #include <boost/geometry/geometries/polygon.hpp>
  18. #include <boost/geometry/algorithms/centroid.hpp>
  19. #include <boost/geometry/strategies/transform.hpp>
  20. #include <boost/geometry/strategies/transform/matrix_transformers.hpp>
  21. #include <boost/geometry/io/wkt/read.hpp>
  22. #if defined(HAVE_SVG)
  23. # include <boost/geometry/io/svg/write.hpp>
  24. #endif
  25. #include <boost/random.hpp>
  26. #include <boost/range.hpp>
  27. #include <boost/shared_ptr.hpp>
  28. using namespace boost::geometry;
  29. struct random_style
  30. {
  31. random_style()
  32. : rng(static_cast<int>(std::time(0))), dist(0, 255), colour(rng, dist)
  33. {}
  34. std::string fill(double opacity = 1)
  35. {
  36. std::ostringstream oss;
  37. oss << "fill:rgba(" << colour() << "," << colour() << "," << colour() << "," << opacity << ");";
  38. return oss.str();
  39. }
  40. std::string stroke(int width, double opacity = 1)
  41. {
  42. std::ostringstream oss;
  43. oss << "stroke:rgba(" << colour() << "," << colour() << "," << colour() << "," << opacity << ");";
  44. oss << "stroke-width:" << width << ";";
  45. return oss.str();
  46. }
  47. template <typename T>
  48. std::string text(T x, T y, std::string const& text)
  49. {
  50. std::ostringstream oss;
  51. oss << "<text x=\"" << static_cast<int>(x) - 90 << "\" y=\"" << static_cast<int>(y) << "\" font-family=\"Verdana\">" << text << "</text>";
  52. return oss.str();
  53. }
  54. boost::mt19937 rng;
  55. boost::uniform_int<> dist;
  56. boost::variate_generator<boost::mt19937&, boost::uniform_int<> > colour;
  57. };
  58. template <typename OutputStream>
  59. struct svg_output
  60. {
  61. svg_output(OutputStream& os, double opacity = 1) : os(os), opacity(opacity)
  62. {
  63. os << "<?xml version=\"1.0\" standalone=\"no\"?>\n"
  64. << "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n"
  65. << "\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n"
  66. << "<svg width=\"100%\" height=\"100%\" version=\"1.1\"\n"
  67. << "xmlns=\"http://www.w3.org/2000/svg\">" << std::endl;
  68. }
  69. ~svg_output()
  70. {
  71. os << "</svg>" << std::endl;
  72. }
  73. template <typename G>
  74. void put(G const& g, std::string const& label)
  75. {
  76. std::string style_str(style.fill(opacity) + style.stroke(5, opacity));
  77. #if defined(HAVE_SVG)
  78. os << boost::geometry::svg(g, style_str) << std::endl;
  79. #endif
  80. if (!label.empty())
  81. {
  82. typename point_type<G>::type c;
  83. centroid(g, c);
  84. os << style.text(static_cast<int>(get<0>(c)), static_cast<int>(get<1>(c)), label);
  85. }
  86. }
  87. private:
  88. OutputStream& os;
  89. double opacity;
  90. random_style style;
  91. };
  92. int main()
  93. {
  94. using namespace boost::geometry::strategy::transform;
  95. typedef boost::geometry::model::d2::point_xy<double> point_2d;
  96. try
  97. {
  98. std::string file("06_b_transformation_example.svg");
  99. std::ofstream ofs(file.c_str());
  100. svg_output<std::ofstream> svg(ofs, 0.5);
  101. // G1 - create subject for affine transformations
  102. model::polygon<point_2d> g1;
  103. read_wkt("POLYGON((50 250, 400 250, 150 50, 50 250))", g1);
  104. std::clog << "source box:\t" << boost::geometry::dsv(g1) << std::endl;
  105. svg.put(g1, "g1");
  106. // G1 - Translate -> G2
  107. translate_transformer<double, 2, 2> translate(0, 250);
  108. model::polygon<point_2d> g2;
  109. transform(g1, g2, translate);
  110. std::clog << "translated:\t" << boost::geometry::dsv(g2) << std::endl;
  111. svg.put(g2, "g2=g1.translate(0,250)");
  112. // G2 - Scale -> G3
  113. scale_transformer<double, 2, 2> scale(0.5, 0.5);
  114. model::polygon<point_2d> g3;
  115. transform(g2, g3, scale);
  116. std::clog << "scaled:\t" << boost::geometry::dsv(g3) << std::endl;
  117. svg.put(g3, "g3=g2.scale(0.5,0.5)");
  118. // G3 - Combine rotate and translate -> G4
  119. rotate_transformer<degree, double, 2, 2> rotate(45);
  120. // Compose matrix for the two transformation
  121. // Create transformer attached to the transformation matrix
  122. matrix_transformer<double, 2, 2> combined(rotate.matrix() * translate.matrix());
  123. // Apply transformation to subject geometry point-by-point
  124. model::polygon<point_2d> g4;
  125. transform(g3, g4, combined);
  126. std::clog << "rotated & translated:\t" << boost::geometry::dsv(g4) << std::endl;
  127. svg.put(g4, "g4 = g3.(rotate(45) * translate(0,250))");
  128. std::clog << "Saved SVG file:\t" << file << std::endl;
  129. }
  130. catch (std::exception const& e)
  131. {
  132. std::cerr << e.what() << std::endl;
  133. }
  134. catch (...)
  135. {
  136. std::cerr << "unknown error" << std::endl;
  137. }
  138. return 0;
  139. }