x06_qt_world_mapper.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. //
  3. // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
  4. // Use, modification and distribution is subject to the Boost Software License,
  5. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. // Qt World Mapper Example
  8. // Qt is a well-known and often used platform independent windows library
  9. // To build and run this example:
  10. // 1) download (from http://qt.nokia.com), configure and make QT
  11. // 2) if necessary, adapt Qt clause in include path (note there is a Qt property sheet)
  12. #include <fstream>
  13. #include <QtGui>
  14. #include <QWidget>
  15. #include <QObject>
  16. #include <QPainter>
  17. #include <boost/foreach.hpp>
  18. #include <boost/geometry/geometry.hpp>
  19. #include <boost/geometry/geometries/geometries.hpp>
  20. #include <boost/geometry/geometries/multi_geometries.hpp>
  21. #include <boost/geometry/geometries/point_xy.hpp>
  22. #include <boost/geometry/geometries/register/point.hpp>
  23. #include <boost/geometry/geometries/register/ring.hpp>
  24. #include <boost/geometry/extensions/algorithms/selected.hpp>
  25. // Adapt a QPointF such that it can be handled by Boost.Geometry
  26. BOOST_GEOMETRY_REGISTER_POINT_2D_GET_SET(QPointF, double, cs::cartesian, x, y, setX, setY)
  27. // Adapt a QPolygonF as well.
  28. // A QPolygonF has no holes (interiors) so it is similar to a Boost.Geometry ring
  29. BOOST_GEOMETRY_REGISTER_RING(QPolygonF)
  30. typedef boost::geometry::model::d2::point_xy<double> point_2d;
  31. typedef boost::geometry::model::multi_polygon
  32. <
  33. boost::geometry::model::polygon<point_2d>
  34. > country_type;
  35. class WorldMapper : public QWidget
  36. {
  37. public:
  38. WorldMapper(std::vector<country_type> const& countries, boost::geometry::model::box<point_2d> const& box)
  39. : m_countries(countries)
  40. , m_box(box)
  41. {
  42. setPalette(QPalette(QColor(200, 250, 250)));
  43. setAutoFillBackground(true);
  44. }
  45. protected:
  46. void paintEvent(QPaintEvent*)
  47. {
  48. map_transformer_type transformer(m_box, this->width(), this->height());
  49. QPainter painter(this);
  50. painter.setBrush(Qt::green);
  51. painter.setRenderHint(QPainter::Antialiasing);
  52. BOOST_FOREACH(country_type const& country, m_countries)
  53. {
  54. typedef boost::range_value<country_type>::type polygon_type;
  55. BOOST_FOREACH(polygon_type const& polygon, country)
  56. {
  57. typedef boost::geometry::ring_type<polygon_type>::type ring_type;
  58. ring_type const& ring = boost::geometry::exterior_ring(polygon);
  59. // This is the essention:
  60. // Directly transform from a multi_polygon (ring-type) to a QPolygonF
  61. QPolygonF qring;
  62. boost::geometry::transform(ring, qring, transformer);
  63. painter.drawPolygon(qring);
  64. }
  65. }
  66. }
  67. private:
  68. typedef boost::geometry::strategy::transform::map_transformer
  69. <
  70. double, 2, 2,
  71. true, true
  72. > map_transformer_type;
  73. std::vector<country_type> const& m_countries;
  74. boost::geometry::model::box<point_2d> const& m_box;
  75. };
  76. class MapperWidget : public QWidget
  77. {
  78. public:
  79. MapperWidget(std::vector<country_type> const& countries, boost::geometry::model::box<point_2d> const& box, QWidget *parent = 0)
  80. : QWidget(parent)
  81. {
  82. WorldMapper* mapper = new WorldMapper(countries, box);
  83. QPushButton *quit = new QPushButton(tr("Quit"));
  84. quit->setFont(QFont("Times", 18, QFont::Bold));
  85. connect(quit, SIGNAL(clicked()), qApp, SLOT(quit()));
  86. QVBoxLayout *layout = new QVBoxLayout;
  87. layout->addWidget(mapper);
  88. layout->addWidget(quit);
  89. setLayout(layout);
  90. }
  91. };
  92. // ----------------------------------------------------------------------------
  93. // Read an ASCII file containing WKT's
  94. // ----------------------------------------------------------------------------
  95. template <typename Geometry, typename Box>
  96. inline void read_wkt(std::string const& filename, std::vector<Geometry>& geometries, Box& box)
  97. {
  98. std::ifstream cpp_file(filename.c_str());
  99. if (cpp_file.is_open())
  100. {
  101. while (! cpp_file.eof() )
  102. {
  103. std::string line;
  104. std::getline(cpp_file, line);
  105. if (! line.empty())
  106. {
  107. Geometry geometry;
  108. boost::geometry::read_wkt(line, geometry);
  109. geometries.push_back(geometry);
  110. boost::geometry::expand(box, boost::geometry::return_envelope<Box>(geometry));
  111. }
  112. }
  113. }
  114. }
  115. int main(int argc, char *argv[])
  116. {
  117. std::vector<country_type> countries;
  118. boost::geometry::model::box<point_2d> box;
  119. boost::geometry::assign_inverse(box);
  120. read_wkt("../data/world.wkt", countries, box);
  121. QApplication app(argc, argv);
  122. MapperWidget widget(countries, box);
  123. widget.setWindowTitle("Boost.Geometry for Qt - Hello World!");
  124. widget.setGeometry(50, 50, 800, 500);
  125. widget.show();
  126. return app.exec();
  127. }