| // Boost.Geometry (aka GGL, Generic Geometry Library) |
| // |
| // Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. |
| // Use, modification and distribution is subject to the Boost Software License, |
| // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
| // http://www.boost.org/LICENSE_1_0.txt) |
| |
| // Qt World Mapper Example |
| |
| // Qt is a well-known and often used platform independent windows library |
| |
| // To build and run this example: |
| // 1) download (from http://qt.nokia.com), configure and make QT |
| // 2) if necessary, adapt Qt clause in include path (note there is a Qt property sheet) |
| |
| #include <fstream> |
| |
| #include <QtGui> |
| #include <QWidget> |
| #include <QObject> |
| #include <QPainter> |
| |
| #include <boost/foreach.hpp> |
| |
| #include <boost/geometry/geometry.hpp> |
| #include <boost/geometry/geometries/point_xy.hpp> |
| #include <boost/geometry/geometries/register/point.hpp> |
| #include <boost/geometry/geometries/register/ring.hpp> |
| |
| #include <boost/geometry/multi/multi.hpp> |
| #include <boost/geometry/extensions/algorithms/selected.hpp> |
| #include <boost/geometry/domains/gis/io/wkt/wkt.hpp> |
| |
| |
| |
| // Adapt a QPointF such that it can be handled by Boost.Geometry |
| BOOST_GEOMETRY_REGISTER_POINT_2D_GET_SET(QPointF, double, cs::cartesian, x, y, setX, setY) |
| |
| // Adapt a QPolygonF as well. |
| // A QPolygonF has no holes (interiors) so it is similar to a Boost.Geometry ring |
| BOOST_GEOMETRY_REGISTER_RING(QPolygonF) |
| |
| |
| typedef boost::geometry::model::d2::point_xy<double> point_2d; |
| typedef boost::geometry::model::multi_polygon |
| < |
| boost::geometry::model::polygon<point_2d> |
| > country_type; |
| |
| |
| class WorldMapper : public QWidget |
| { |
| public: |
| WorldMapper(std::vector<country_type> const& countries, boost::geometry::model::box<point_2d> const& box) |
| : m_countries(countries) |
| , m_box(box) |
| { |
| setPalette(QPalette(QColor(200, 250, 250))); |
| setAutoFillBackground(true); |
| } |
| |
| protected: |
| void paintEvent(QPaintEvent*) |
| { |
| map_transformer_type transformer(m_box, this->width(), this->height()); |
| |
| QPainter painter(this); |
| painter.setBrush(Qt::green); |
| painter.setRenderHint(QPainter::Antialiasing); |
| |
| BOOST_FOREACH(country_type const& country, m_countries) |
| { |
| typedef boost::range_value<country_type>::type polygon_type; |
| BOOST_FOREACH(polygon_type const& polygon, country) |
| { |
| typedef boost::geometry::ring_type<polygon_type>::type ring_type; |
| ring_type const& ring = boost::geometry::exterior_ring(polygon); |
| |
| // This is the essention: |
| // Directly transform from a multi_polygon (ring-type) to a QPolygonF |
| QPolygonF qring; |
| boost::geometry::transform(ring, qring, transformer); |
| |
| painter.drawPolygon(qring); |
| } |
| } |
| } |
| |
| private: |
| typedef boost::geometry::strategy::transform::map_transformer |
| < |
| point_2d, QPointF, |
| true, true |
| > map_transformer_type; |
| |
| std::vector<country_type> const& m_countries; |
| boost::geometry::model::box<point_2d> const& m_box; |
| }; |
| |
| |
| class MapperWidget : public QWidget |
| { |
| public: |
| MapperWidget(std::vector<country_type> const& countries, boost::geometry::model::box<point_2d> const& box, QWidget *parent = 0) |
| : QWidget(parent) |
| { |
| WorldMapper* mapper = new WorldMapper(countries, box); |
| |
| QPushButton *quit = new QPushButton(tr("Quit")); |
| quit->setFont(QFont("Times", 18, QFont::Bold)); |
| connect(quit, SIGNAL(clicked()), qApp, SLOT(quit())); |
| |
| QVBoxLayout *layout = new QVBoxLayout; |
| layout->addWidget(mapper); |
| layout->addWidget(quit); |
| setLayout(layout); |
| } |
| |
| }; |
| |
| |
| // ---------------------------------------------------------------------------- |
| // Read an ASCII file containing WKT's |
| // ---------------------------------------------------------------------------- |
| template <typename Geometry, typename Box> |
| inline void read_wkt(std::string const& filename, std::vector<Geometry>& geometries, Box& box) |
| { |
| std::ifstream cpp_file(filename.c_str()); |
| if (cpp_file.is_open()) |
| { |
| while (! cpp_file.eof() ) |
| { |
| std::string line; |
| std::getline(cpp_file, line); |
| if (! line.empty()) |
| { |
| Geometry geometry; |
| boost::geometry::read_wkt(line, geometry); |
| geometries.push_back(geometry); |
| boost::geometry::expand(box, boost::geometry::return_envelope<Box>(geometry)); |
| } |
| } |
| } |
| } |
| |
| |
| int main(int argc, char *argv[]) |
| { |
| std::vector<country_type> countries; |
| boost::geometry::model::box<point_2d> box; |
| boost::geometry::assign_inverse(box); |
| read_wkt("../data/world.wkt", countries, box); |
| |
| QApplication app(argc, argv); |
| MapperWidget widget(countries, box); |
| widget.setWindowTitle("Boost.Geometry for Qt - Hello World!"); |
| widget.setGeometry(50, 50, 800, 500); |
| widget.show(); |
| return app.exec(); |
| } |