123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393 |
- // Boost.Geometry (aka GGL, Generic Geometry Library)
- //
- // Copyright (c) 2010-2012 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)
- //
- // wxWidgets World Mapper example
- // #define EXAMPLE_WX_USE_GRAPHICS_CONTEXT 1
- #include <fstream>
- #include <sstream>
- #include <boost/foreach.hpp>
- #include <boost/shared_ptr.hpp>
- #include <boost/scoped_array.hpp>
- #include <boost/geometry/geometry.hpp>
- #include <boost/geometry/geometries/geometries.hpp>
- #include <boost/geometry/geometries/point_xy.hpp>
- #include <boost/geometry/geometries/multi_geometries.hpp>
- #include <boost/geometry/geometries/register/point.hpp>
- #include <boost/geometry/geometries/register/ring.hpp>
- #include <boost/geometry/extensions/algorithms/selected.hpp>
- // wxWidgets, if these headers are NOT found, adapt include path (and lib path)
- #include "wx/wx.h"
- #include "wx/math.h"
- #include "wx/stockitem.h"
- #ifdef EXAMPLE_WX_USE_GRAPHICS_CONTEXT
- #include "wx/graphics.h"
- #include "wx/dcgraph.h"
- #endif
- typedef boost::geometry::model::d2::point_xy<double> point_2d;
- typedef boost::geometry::model::multi_polygon
- <
- boost::geometry::model::polygon<point_2d>
- > country_type;
- // Adapt wxWidgets points to Boost.Geometry points such that they can be used
- // in e.g. transformations (see below)
- BOOST_GEOMETRY_REGISTER_POINT_2D(wxPoint, int, cs::cartesian, x, y)
- BOOST_GEOMETRY_REGISTER_POINT_2D(wxRealPoint, double, cs::cartesian, x, y)
- // wxWidgets draws using wxPoint*, so we HAVE to use that.
- // Therefore have to make a wxPoint* array
- // 1) compatible with Boost.Geometry
- // 2) compatible with Boost.Range (required by Boost.Geometry)
- // 3) compatible with std::back_inserter (required by Boost.Geometry)
- // For compatible 2):
- typedef std::pair<wxPoint*,wxPoint*> wxPointPointerPair;
- // For compatible 1):
- BOOST_GEOMETRY_REGISTER_RING(wxPointPointerPair);
- // For compatible 3):
- // Specialize back_insert_iterator for the wxPointPointerPair
- // (has to be done within "namespace std")
- namespace std
- {
- template <>
- class back_insert_iterator<wxPointPointerPair>
- {
- public:
- typedef std::output_iterator_tag iterator_category;
- typedef void value_type;
- typedef void difference_type;
- typedef void pointer;
- typedef void reference;
- typedef wxPointPointerPair container_type;
- explicit back_insert_iterator(wxPointPointerPair& x)
- : current(boost::begin(x))
- , end(boost::end(x))
- {}
- inline back_insert_iterator<wxPointPointerPair>&
- operator=(wxPoint const& value)
- {
- // Check if not passed beyond
- if (current != end)
- {
- *current++ = value;
- }
- return *this;
- }
- // Boiler-plate
- inline back_insert_iterator<wxPointPointerPair>& operator*() { return *this; }
- inline back_insert_iterator<wxPointPointerPair>& operator++() { return *this; }
- inline back_insert_iterator<wxPointPointerPair>& operator++(int) { return *this; }
- private:
- boost::range_iterator<wxPointPointerPair>::type current, end;
- };
- } // namespace std
- // ----------------------------------------------------------------------------
- // 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));
- }
- }
- }
- }
- // ----------------------------------------------------------------------------
- class HelloWorldFrame: public wxFrame
- {
- public:
- HelloWorldFrame(wxFrame *frame, wxString const& title, wxPoint const& pos, wxSize const& size);
- void OnCloseWindow(wxCloseEvent& );
- void OnExit(wxCommandEvent& );
- DECLARE_EVENT_TABLE()
- };
- // ----------------------------------------------------------------------------
- class HelloWorldCanvas: public wxWindow
- {
- public:
- HelloWorldCanvas(wxFrame *frame);
- private:
- void DrawCountries(wxDC& dc);
- void DrawCountry(wxDC& dc, country_type const& country);
- void OnPaint(wxPaintEvent& );
- void OnMouseMove(wxMouseEvent&);
- typedef boost::geometry::strategy::transform::map_transformer
- <
- double, 2, 2,
- true, true
- > map_transformer_type;
- typedef boost::geometry::strategy::transform::inverse_transformer
- <
- double, 2, 2
- > inverse_transformer_type;
- boost::shared_ptr<map_transformer_type> m_map_transformer;
- boost::shared_ptr<inverse_transformer_type> m_inverse_transformer;
- boost::geometry::model::box<point_2d> m_box;
- std::vector<country_type> m_countries;
- int m_focus;
- wxBrush m_orange;
- wxFrame* m_owner;
- DECLARE_EVENT_TABLE()
- };
- // ----------------------------------------------------------------------------
- class HelloWorldApp: public wxApp
- {
- public:
- bool OnInit()
- {
- // Create the main frame window
- HelloWorldFrame *frame = new HelloWorldFrame(NULL, _T("Boost.Geometry for wxWidgets - Hello World!"), wxDefaultPosition, wxSize(640, 480));
- wxMenu *file_menu = new wxMenu;
- file_menu->Append(wxID_EXIT, wxGetStockLabel(wxID_EXIT));
- wxMenuBar* menuBar = new wxMenuBar;
- menuBar->Append(file_menu, _T("&File"));
- frame->SetMenuBar(menuBar);
- int width, height;
- frame->GetClientSize(&width, &height);
- (void) new HelloWorldCanvas(frame);
- // Show the frame
- frame->Show(true);
- return true;
- }
- };
- // ----------------------------------------------------------------------------
- HelloWorldFrame::HelloWorldFrame(wxFrame *frame, wxString const& title, wxPoint const& pos, wxSize const& size)
- : wxFrame(frame, wxID_ANY, title, pos, size, wxDEFAULT_FRAME_STYLE | wxFULL_REPAINT_ON_RESIZE )
- {
- CreateStatusBar(2);
- }
- void HelloWorldFrame::OnExit(wxCommandEvent& )
- {
- this->Destroy();
- }
- void HelloWorldFrame::OnCloseWindow(wxCloseEvent& )
- {
- static bool destroyed = false;
- if (! destroyed)
- {
- this->Destroy();
- destroyed = true;
- }
- }
- // ----------------------------------------------------------------------------
- HelloWorldCanvas::HelloWorldCanvas(wxFrame *frame)
- : wxWindow(frame, wxID_ANY)
- , m_owner(frame)
- , m_focus(-1)
- {
- boost::geometry::assign_inverse(m_box);
- read_wkt("../data/world.wkt", m_countries, m_box);
- m_orange = wxBrush(wxColour(255, 128, 0), wxSOLID);
- }
- void HelloWorldCanvas::OnMouseMove(wxMouseEvent &event)
- {
- namespace bg = boost::geometry;
- if (m_inverse_transformer)
- {
- // Boiler-plate wxWidgets code
- wxClientDC dc(this);
- PrepareDC(dc);
- m_owner->PrepareDC(dc);
- // Transform the point to Lon/Lat
- point_2d point;
- bg::transform(event.GetPosition(), point, *m_inverse_transformer);
- // Determine selected object
- int i = 0;
- int previous_focus = m_focus;
- m_focus = -1;
- BOOST_FOREACH(country_type const& country, m_countries)
- {
- if (bg::selected(country, point, 0))
- {
- m_focus = i;
- }
- i++;
- }
- // On change:
- if (m_focus != previous_focus)
- {
- // Undraw old focus
- if (previous_focus >= 0)
- {
- dc.SetBrush(*wxWHITE_BRUSH);
- DrawCountry(dc, m_countries[previous_focus]);
- }
- // Draw new focus
- if (m_focus >= 0)
- {
- dc.SetBrush(m_orange);
- DrawCountry(dc, m_countries[m_focus]);
- }
- }
- // Create a string and set it in the status text
- std::ostringstream out;
- out << "Position: " << point.x() << ", " << point.y();
- m_owner->SetStatusText(wxString(out.str().c_str(), wxConvUTF8));
- }
- }
- void HelloWorldCanvas::OnPaint(wxPaintEvent& )
- {
- #if defined(EXAMPLE_WX_USE_GRAPHICS_CONTEXT)
- wxPaintDC pdc(this);
- wxGCDC gdc(pdc);
- wxDC& dc = (wxDC&) gdc;
- #else
- wxPaintDC dc(this);
- #endif
- PrepareDC(dc);
- static bool running = false;
- if (! running)
- {
- running = true;
- // Update the transformers
- wxSize sz = dc.GetSize();
- m_map_transformer.reset(new map_transformer_type(m_box, sz.x, sz.y));
- m_inverse_transformer.reset(new inverse_transformer_type(*m_map_transformer));
- DrawCountries(dc);
- running = false;
- }
- }
- void HelloWorldCanvas::DrawCountries(wxDC& dc)
- {
- namespace bg = boost::geometry;
- dc.SetBackground(*wxLIGHT_GREY_BRUSH);
- dc.Clear();
- BOOST_FOREACH(country_type const& country, m_countries)
- {
- DrawCountry(dc, country);
- }
- if (m_focus != -1)
- {
- dc.SetBrush(m_orange);
- DrawCountry(dc, m_countries[m_focus]);
- }
- }
- void HelloWorldCanvas::DrawCountry(wxDC& dc, country_type const& country)
- {
- namespace bg = boost::geometry;
- BOOST_FOREACH(bg::model::polygon<point_2d> const& poly, country)
- {
- // Use only exterior ring, holes are (for the moment) ignored. This would need
- // a holey-polygon compatible wx object
- std::size_t n = boost::size(bg::exterior_ring(poly));
- boost::scoped_array<wxPoint> points(new wxPoint[n]);
- wxPointPointerPair pair = std::make_pair(points.get(), points.get() + n);
- bg::transform(bg::exterior_ring(poly), pair, *m_map_transformer);
- dc.DrawPolygon(n, points.get());
- }
- }
- // ----------------------------------------------------------------------------
- BEGIN_EVENT_TABLE(HelloWorldFrame, wxFrame)
- EVT_CLOSE(HelloWorldFrame::OnCloseWindow)
- EVT_MENU(wxID_EXIT, HelloWorldFrame::OnExit)
- END_EVENT_TABLE()
- BEGIN_EVENT_TABLE(HelloWorldCanvas, wxWindow)
- EVT_PAINT(HelloWorldCanvas::OnPaint)
- EVT_MOTION(HelloWorldCanvas::OnMouseMove)
- END_EVENT_TABLE()
- IMPLEMENT_APP(HelloWorldApp)
|