]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/geometry/example/with_external_libs/x04_wxwidgets_world_mapper.cpp
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / boost / libs / geometry / example / with_external_libs / x04_wxwidgets_world_mapper.cpp
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 //
3 // Copyright (c) 2010-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 //
8 // wxWidgets World Mapper example
9
10
11 // #define EXAMPLE_WX_USE_GRAPHICS_CONTEXT 1
12
13 #include <fstream>
14 #include <sstream>
15
16 #include <boost/foreach.hpp>
17 #include <boost/shared_ptr.hpp>
18 #include <boost/scoped_array.hpp>
19
20 #include <boost/geometry/geometry.hpp>
21 #include <boost/geometry/geometries/geometries.hpp>
22 #include <boost/geometry/geometries/point_xy.hpp>
23 #include <boost/geometry/geometries/multi_geometries.hpp>
24
25 #include <boost/geometry/geometries/register/point.hpp>
26 #include <boost/geometry/geometries/register/ring.hpp>
27 #include <boost/geometry/extensions/algorithms/selected.hpp>
28
29
30 // wxWidgets, if these headers are NOT found, adapt include path (and lib path)
31
32 #include "wx/wx.h"
33 #include "wx/math.h"
34 #include "wx/stockitem.h"
35
36
37 #ifdef EXAMPLE_WX_USE_GRAPHICS_CONTEXT
38 #include "wx/graphics.h"
39 #include "wx/dcgraph.h"
40 #endif
41
42 typedef boost::geometry::model::d2::point_xy<double> point_2d;
43 typedef boost::geometry::model::multi_polygon
44 <
45 boost::geometry::model::polygon<point_2d>
46 > country_type;
47
48 // Adapt wxWidgets points to Boost.Geometry points such that they can be used
49 // in e.g. transformations (see below)
50 BOOST_GEOMETRY_REGISTER_POINT_2D(wxPoint, int, cs::cartesian, x, y)
51 BOOST_GEOMETRY_REGISTER_POINT_2D(wxRealPoint, double, cs::cartesian, x, y)
52
53
54 // wxWidgets draws using wxPoint*, so we HAVE to use that.
55 // Therefore have to make a wxPoint* array
56 // 1) compatible with Boost.Geometry
57 // 2) compatible with Boost.Range (required by Boost.Geometry)
58 // 3) compatible with std::back_inserter (required by Boost.Geometry)
59
60 // For compatible 2):
61 typedef std::pair<wxPoint*,wxPoint*> wxPointPointerPair;
62
63 // For compatible 1):
64 BOOST_GEOMETRY_REGISTER_RING(wxPointPointerPair);
65
66
67 // For compatible 3):
68 // Specialize back_insert_iterator for the wxPointPointerPair
69 // (has to be done within "namespace std")
70 namespace std
71 {
72
73 template <>
74 class back_insert_iterator<wxPointPointerPair>
75 {
76 public:
77 typedef std::output_iterator_tag iterator_category;
78 typedef void value_type;
79 typedef void difference_type;
80 typedef void pointer;
81 typedef void reference;
82
83 typedef wxPointPointerPair container_type;
84
85 explicit back_insert_iterator(wxPointPointerPair& x)
86 : current(boost::begin(x))
87 , end(boost::end(x))
88 {}
89
90 inline back_insert_iterator<wxPointPointerPair>&
91 operator=(wxPoint const& value)
92 {
93 // Check if not passed beyond
94 if (current != end)
95 {
96 *current++ = value;
97 }
98 return *this;
99 }
100
101 // Boiler-plate
102 inline back_insert_iterator<wxPointPointerPair>& operator*() { return *this; }
103 inline back_insert_iterator<wxPointPointerPair>& operator++() { return *this; }
104 inline back_insert_iterator<wxPointPointerPair>& operator++(int) { return *this; }
105
106 private:
107 boost::range_iterator<wxPointPointerPair>::type current, end;
108 };
109
110 } // namespace std
111
112
113 // ----------------------------------------------------------------------------
114 // Read an ASCII file containing WKT's
115 // ----------------------------------------------------------------------------
116 template <typename Geometry, typename Box>
117 inline void read_wkt(std::string const& filename, std::vector<Geometry>& geometries, Box& box)
118 {
119 std::ifstream cpp_file(filename.c_str());
120 if (cpp_file.is_open())
121 {
122 while (! cpp_file.eof() )
123 {
124 std::string line;
125 std::getline(cpp_file, line);
126 if (! line.empty())
127 {
128 Geometry geometry;
129 boost::geometry::read_wkt(line, geometry);
130 geometries.push_back(geometry);
131 boost::geometry::expand(box, boost::geometry::return_envelope<Box>(geometry));
132 }
133 }
134 }
135 }
136
137
138 // ----------------------------------------------------------------------------
139 class HelloWorldFrame: public wxFrame
140 {
141 public:
142 HelloWorldFrame(wxFrame *frame, wxString const& title, wxPoint const& pos, wxSize const& size);
143
144 void OnCloseWindow(wxCloseEvent& );
145 void OnExit(wxCommandEvent& );
146
147 DECLARE_EVENT_TABLE()
148 };
149
150
151 // ----------------------------------------------------------------------------
152 class HelloWorldCanvas: public wxWindow
153 {
154 public:
155 HelloWorldCanvas(wxFrame *frame);
156
157 private:
158 void DrawCountries(wxDC& dc);
159 void DrawCountry(wxDC& dc, country_type const& country);
160
161 void OnPaint(wxPaintEvent& );
162 void OnMouseMove(wxMouseEvent&);
163
164 typedef boost::geometry::strategy::transform::map_transformer
165 <
166 double, 2, 2,
167 true, true
168 > map_transformer_type;
169
170 typedef boost::geometry::strategy::transform::inverse_transformer
171 <
172 double, 2, 2
173 > inverse_transformer_type;
174
175 boost::shared_ptr<map_transformer_type> m_map_transformer;
176 boost::shared_ptr<inverse_transformer_type> m_inverse_transformer;
177
178 boost::geometry::model::box<point_2d> m_box;
179 std::vector<country_type> m_countries;
180 int m_focus;
181
182 wxBrush m_orange;
183 wxFrame* m_owner;
184
185 DECLARE_EVENT_TABLE()
186 };
187
188
189
190 // ----------------------------------------------------------------------------
191 class HelloWorldApp: public wxApp
192 {
193 public:
194 bool OnInit()
195 {
196 // Create the main frame window
197 HelloWorldFrame *frame = new HelloWorldFrame(NULL, _T("Boost.Geometry for wxWidgets - Hello World!"), wxDefaultPosition, wxSize(640, 480));
198
199 wxMenu *file_menu = new wxMenu;
200 file_menu->Append(wxID_EXIT, wxGetStockLabel(wxID_EXIT));
201 wxMenuBar* menuBar = new wxMenuBar;
202 menuBar->Append(file_menu, _T("&File"));
203 frame->SetMenuBar(menuBar);
204
205 int width, height;
206 frame->GetClientSize(&width, &height);
207
208 (void) new HelloWorldCanvas(frame);
209
210 // Show the frame
211 frame->Show(true);
212
213 return true;
214 }
215 };
216
217
218
219 // ----------------------------------------------------------------------------
220 HelloWorldFrame::HelloWorldFrame(wxFrame *frame, wxString const& title, wxPoint const& pos, wxSize const& size)
221 : wxFrame(frame, wxID_ANY, title, pos, size, wxDEFAULT_FRAME_STYLE | wxFULL_REPAINT_ON_RESIZE )
222 {
223 CreateStatusBar(2);
224 }
225
226
227 void HelloWorldFrame::OnExit(wxCommandEvent& )
228 {
229 this->Destroy();
230 }
231
232 void HelloWorldFrame::OnCloseWindow(wxCloseEvent& )
233 {
234 static bool destroyed = false;
235 if (! destroyed)
236 {
237 this->Destroy();
238 destroyed = true;
239 }
240 }
241
242
243 // ----------------------------------------------------------------------------
244 HelloWorldCanvas::HelloWorldCanvas(wxFrame *frame)
245 : wxWindow(frame, wxID_ANY)
246 , m_owner(frame)
247 , m_focus(-1)
248 {
249 boost::geometry::assign_inverse(m_box);
250 read_wkt("../data/world.wkt", m_countries, m_box);
251 m_orange = wxBrush(wxColour(255, 128, 0), wxSOLID);
252 }
253
254
255
256 void HelloWorldCanvas::OnMouseMove(wxMouseEvent &event)
257 {
258 namespace bg = boost::geometry;
259
260 if (m_inverse_transformer)
261 {
262 // Boiler-plate wxWidgets code
263 wxClientDC dc(this);
264 PrepareDC(dc);
265 m_owner->PrepareDC(dc);
266
267 // Transform the point to Lon/Lat
268 point_2d point;
269 bg::transform(event.GetPosition(), point, *m_inverse_transformer);
270
271 // Determine selected object
272 int i = 0;
273 int previous_focus = m_focus;
274 m_focus = -1;
275 BOOST_FOREACH(country_type const& country, m_countries)
276 {
277 if (bg::selected(country, point, 0))
278 {
279 m_focus = i;
280 }
281 i++;
282 }
283
284 // On change:
285 if (m_focus != previous_focus)
286 {
287 // Undraw old focus
288 if (previous_focus >= 0)
289 {
290 dc.SetBrush(*wxWHITE_BRUSH);
291 DrawCountry(dc, m_countries[previous_focus]);
292 }
293 // Draw new focus
294 if (m_focus >= 0)
295 {
296 dc.SetBrush(m_orange);
297 DrawCountry(dc, m_countries[m_focus]);
298 }
299 }
300
301 // Create a string and set it in the status text
302 std::ostringstream out;
303 out << "Position: " << point.x() << ", " << point.y();
304 m_owner->SetStatusText(wxString(out.str().c_str(), wxConvUTF8));
305 }
306 }
307
308
309
310 void HelloWorldCanvas::OnPaint(wxPaintEvent& )
311 {
312 #if defined(EXAMPLE_WX_USE_GRAPHICS_CONTEXT)
313 wxPaintDC pdc(this);
314 wxGCDC gdc(pdc);
315 wxDC& dc = (wxDC&) gdc;
316 #else
317 wxPaintDC dc(this);
318 #endif
319
320 PrepareDC(dc);
321
322 static bool running = false;
323 if (! running)
324 {
325 running = true;
326
327 // Update the transformers
328 wxSize sz = dc.GetSize();
329 m_map_transformer.reset(new map_transformer_type(m_box, sz.x, sz.y));
330 m_inverse_transformer.reset(new inverse_transformer_type(*m_map_transformer));
331
332 DrawCountries(dc);
333
334 running = false;
335 }
336 }
337
338
339 void HelloWorldCanvas::DrawCountries(wxDC& dc)
340 {
341 namespace bg = boost::geometry;
342
343 dc.SetBackground(*wxLIGHT_GREY_BRUSH);
344 dc.Clear();
345
346 BOOST_FOREACH(country_type const& country, m_countries)
347 {
348 DrawCountry(dc, country);
349 }
350 if (m_focus != -1)
351 {
352 dc.SetBrush(m_orange);
353 DrawCountry(dc, m_countries[m_focus]);
354 }
355 }
356
357
358 void HelloWorldCanvas::DrawCountry(wxDC& dc, country_type const& country)
359 {
360 namespace bg = boost::geometry;
361
362 BOOST_FOREACH(bg::model::polygon<point_2d> const& poly, country)
363 {
364 // Use only exterior ring, holes are (for the moment) ignored. This would need
365 // a holey-polygon compatible wx object
366
367 std::size_t n = boost::size(bg::exterior_ring(poly));
368
369 boost::scoped_array<wxPoint> points(new wxPoint[n]);
370
371 wxPointPointerPair pair = std::make_pair(points.get(), points.get() + n);
372 bg::transform(bg::exterior_ring(poly), pair, *m_map_transformer);
373
374 dc.DrawPolygon(n, points.get());
375 }
376 }
377
378 // ----------------------------------------------------------------------------
379
380
381 BEGIN_EVENT_TABLE(HelloWorldFrame, wxFrame)
382 EVT_CLOSE(HelloWorldFrame::OnCloseWindow)
383 EVT_MENU(wxID_EXIT, HelloWorldFrame::OnExit)
384 END_EVENT_TABLE()
385
386
387 BEGIN_EVENT_TABLE(HelloWorldCanvas, wxWindow)
388 EVT_PAINT(HelloWorldCanvas::OnPaint)
389 EVT_MOTION(HelloWorldCanvas::OnMouseMove)
390 END_EVENT_TABLE()
391
392
393 IMPLEMENT_APP(HelloWorldApp)