// 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(); }