1
2 ///////////////////////////////////////////////////////////
3 // //
4 // SAGA //
5 // //
6 // System for Automated Geoscientific Analyses //
7 // //
8 // User Interface //
9 // //
10 // Program: SAGA //
11 // //
12 //-------------------------------------------------------//
13 // //
14 // wksp_map_basemap.cpp //
15 // //
16 // Copyright (C) 2016 by Olaf Conrad //
17 // //
18 //-------------------------------------------------------//
19 // //
20 // This file is part of 'SAGA - System for Automated //
21 // Geoscientific Analyses'. SAGA is free software; you //
22 // can redistribute it and/or modify it under the terms //
23 // of the GNU General Public License as published by the //
24 // Free Software Foundation, either version 2 of the //
25 // License, or (at your option) any later version. //
26 // //
27 // SAGA is distributed in the hope that it will be //
28 // useful, but WITHOUT ANY WARRANTY; without even the //
29 // implied warranty of MERCHANTABILITY or FITNESS FOR A //
30 // PARTICULAR PURPOSE. See the GNU General Public //
31 // License for more details. //
32 // //
33 // You should have received a copy of the GNU General //
34 // Public License along with this program; if not, see //
35 // <http://www.gnu.org/licenses/>. //
36 // //
37 //-------------------------------------------------------//
38 // //
39 // contact: Olaf Conrad //
40 // Institute of Geography //
41 // University of Hamburg //
42 // Germany //
43 // //
44 // e-mail: oconrad@saga-gis.org //
45 // //
46 ///////////////////////////////////////////////////////////
47
48 //---------------------------------------------------------
49 #include <wx/window.h>
50
51 #include <saga_api/saga_api.h>
52 #include <saga_gdi/sgdi_helper.h>
53
54 #include "helper.h"
55
56 #include "res_commands.h"
57 #include "res_dialogs.h"
58
59 #include "wksp_map.h"
60 #include "wksp_map_manager.h"
61 #include "wksp_map_basemap.h"
62 #include "wksp_map_dc.h"
63
64
65 ///////////////////////////////////////////////////////////
66 // //
67 // //
68 // //
69 ///////////////////////////////////////////////////////////
70
71 //---------------------------------------------------------
CWKSP_Map_BaseMap(CSG_MetaData * pEntry)72 CWKSP_Map_BaseMap::CWKSP_Map_BaseMap(CSG_MetaData *pEntry)
73 {
74 m_bShow = true;
75 m_pTool = NULL; // remember the last created base map tool instance
76
77 //-----------------------------------------------------
78 m_Parameters.Set_Name ("BASEMAP");
79 m_Parameters.Set_Identifier("BASEMAP");
80
81 //-----------------------------------------------------
82 m_Parameters.Add_Node("", "NODE_GENERAL",_TL("General") , _TL(""));
83
84 m_Parameters.Add_String("NODE_GENERAL",
85 "NAME" , _TL("Name"),
86 _TL(""),
87 _TL("Base Map")
88 );
89
90 m_Parameters.Add_Choice("NODE_GENERAL",
91 "SERVER" , _TL("Server"),
92 _TL(""),
93 CSG_String::Format("%s|%s|%s|%s|%s|%s|%s|%s|%s",
94 _TL("Open Street Map"),
95 _TL("Google Map"),
96 _TL("Google Satellite"),
97 _TL("Google Hybrid"),
98 _TL("Google Terrain"),
99 _TL("Google Terrain, Streets and Water"),
100 _TL("ArcGIS MapServer Tiles"),
101 _TL("TopPlusOpen"),
102 _TL("user defined")
103 ), 0
104 );
105
106 m_Parameters.Add_String("SERVER",
107 "SERVER_USER", _TL("Server"),
108 _TL(""),
109 "tile.openstreetmap.org/${z}/${x}/${y}.png"
110 );
111
112 m_Parameters.Add_Bool("NODE_GENERAL",
113 "CACHE" , _TL("Cache"),
114 _TL("Enable local disk cache. Allows for offline operation."),
115 g_pMaps->Get_Parameter("CACHE")->asBool()
116 );
117
118 m_Parameters.Add_FilePath("CACHE",
119 "CACHE_DIR" , _TL("Cache Directory"),
120 _TL("If not specified the cache will be created in the current user's temporary directory."),
121 NULL, g_pMaps->Get_Parameter("CACHE_DIR")->asString(), false, true
122 );
123
124 //-----------------------------------------------------
125 m_Parameters.Add_Bool("NODE_GENERAL",
126 "SHOW_ALWAYS" , _TL("Show at all scales"),
127 _TL(""),
128 true
129 );
130
131 m_Parameters.Add_Range("NODE_GENERAL",
132 "SHOW_RANGE" , _TL("Scale Range"),
133 _TL("only show within scale range; values are given as extent measured in map units"),
134 100., 1000., 0., true
135 );
136
137 //-----------------------------------------------------
138 m_Parameters.Add_Node("", "NODE_DISPLAY",_TL("Display") , _TL(""));
139
140 m_Parameters.Add_Double("NODE_DISPLAY",
141 "TRANSPARENCY" , _TL("Transparency [%]"),
142 _TL(""),
143 0., 0., true, 100., true
144 );
145
146 m_Parameters.Add_Double("NODE_DISPLAY",
147 "BRIGHTNESS" , _TL("Maximum Brightness [%]"),
148 _TL("Brightness threshold below a pixel is displayed. Set to 100% to display all (default)."),
149 100., 0., true, 100., true
150 );
151
152 m_Parameters.Add_Bool("NODE_DISPLAY",
153 "GRAYSCALE" , _TL("Gray Scale Image"),
154 _TL(""),
155 false
156 );
157
158 m_Parameters.Add_Double("NODE_DISPLAY",
159 "RESOLUTION" , _TL("Resolution"),
160 _TL("resolution measured in screen pixels"),
161 1., 1., true
162 );
163
164 //-----------------------------------------------------
165 m_Parameters.Add_Choice("NODE_DISPLAY",
166 "POSITION" , _TL("Position"),
167 _TL(""),
168 CSG_String::Format("%s|%s",
169 _TL("top"),
170 _TL("bottom")
171 ), 1
172 )->Set_Enabled(false);
173
174 //-----------------------------------------------------
175 if( pEntry )
176 {
177 Load(*pEntry);
178 }
179 }
180
181 //---------------------------------------------------------
~CWKSP_Map_BaseMap(void)182 CWKSP_Map_BaseMap::~CWKSP_Map_BaseMap(void)
183 {}
184
185
186 ///////////////////////////////////////////////////////////
187 // //
188 ///////////////////////////////////////////////////////////
189
190 //---------------------------------------------------------
Load(CSG_MetaData & Entry)191 bool CWKSP_Map_BaseMap::Load(CSG_MetaData &Entry)
192 {
193 return( m_Parameters.Serialize(Entry, false) );
194 }
195
196 //---------------------------------------------------------
Save(CSG_MetaData & Entry)197 bool CWKSP_Map_BaseMap::Save(CSG_MetaData &Entry)
198 {
199 return( m_Parameters.Serialize(*Entry.Add_Child("BASEMAP"), true) );
200 }
201
202
203 ///////////////////////////////////////////////////////////
204 // //
205 ///////////////////////////////////////////////////////////
206
207 //---------------------------------------------------------
Get_Name(void)208 wxString CWKSP_Map_BaseMap::Get_Name(void)
209 {
210 wxString Name(m_Parameters("NAME")->asString());
211
212 return( !m_bShow ? "* " + Name : Name );
213 }
214
215 //---------------------------------------------------------
Get_Description(void)216 wxString CWKSP_Map_BaseMap::Get_Description(void)
217 {
218 wxString s;
219
220 //-----------------------------------------------------
221 s += wxString::Format("<h4>%s</h4>", _TL("Base Map"));
222
223 s += "<table border=\"0\">";
224
225 DESC_ADD_STR(_TL("Name" ), m_Parameters("NAME")->asString());
226 DESC_ADD_STR(_TL("Projection"), Get_Map()->Get_Projection().Get_Description().c_str());
227
228 s += wxT("</table>");
229
230 //-----------------------------------------------------
231 s += "<hr>";
232 s += _TL("Be sure to read and understand the usage agreement or terms of service before you use a base map server.");
233 s += "<ul>";
234 s += "<li><a href=\"www.openstreetmap.org\">Open Street Map</a></li>";
235 // s += "<li><a href=\"open.mapquest.co.uk\">MapQuest</a></li>";
236 s += "<li><a href=\"maps.google.com/intl/en/help/terms_maps.html\">Google Maps</a></li>";
237 s += "<li><a href=\"services.arcgisonline.com\">ArcGIS MapServer</a></li>";
238 s += "<li><a href=\"www.geodatenzentrum.de/geodaten/gdz_rahmen.gdz_div\">TopPlusOpen</a></li>";
239 s += "</ul>";
240
241 //-----------------------------------------------------
242 return( s );
243 }
244
245 //---------------------------------------------------------
Get_Menu(void)246 wxMenu * CWKSP_Map_BaseMap::Get_Menu(void)
247 {
248 wxMenu *pMenu = new wxMenu(m_Parameters("NAME")->asString());
249
250 CMD_Menu_Add_Item(pMenu, false, ID_CMD_WKSP_ITEM_CLOSE);
251 CMD_Menu_Add_Item(pMenu, true, ID_CMD_MAPS_LAYER_SHOW);
252 pMenu->AppendSeparator();
253 CMD_Menu_Add_Item(pMenu, false, ID_CMD_MAPS_MOVE_TOP);
254 CMD_Menu_Add_Item(pMenu, false, ID_CMD_MAPS_MOVE_UP);
255 CMD_Menu_Add_Item(pMenu, false, ID_CMD_MAPS_MOVE_DOWN);
256 CMD_Menu_Add_Item(pMenu, false, ID_CMD_MAPS_MOVE_BOTTOM);
257
258 return( pMenu );
259 }
260
261
262 ///////////////////////////////////////////////////////////
263 // //
264 ///////////////////////////////////////////////////////////
265
266 //---------------------------------------------------------
On_Command(int Cmd_ID)267 bool CWKSP_Map_BaseMap::On_Command(int Cmd_ID)
268 {
269 switch( Cmd_ID )
270 {
271 default:
272 return( CWKSP_Base_Item::On_Command(Cmd_ID) );
273
274 case ID_CMD_WKSP_ITEM_RETURN:
275 case ID_CMD_MAPS_LAYER_SHOW:
276 m_bShow = !m_bShow;
277 ((wxTreeCtrl *)Get_Control())->SetItemText(GetId(), Get_Name());
278 ((CWKSP_Map *)Get_Manager())->View_Refresh(true);
279 break;
280
281 case ID_CMD_MAPS_MOVE_TOP:
282 if( Get_Manager()->Move_Top(this) )
283 ((CWKSP_Map *)Get_Manager())->View_Refresh(false);
284 break;
285
286 case ID_CMD_MAPS_MOVE_BOTTOM:
287 if( Get_Manager()->Move_Bottom(this) )
288 ((CWKSP_Map *)Get_Manager())->View_Refresh(false);
289 break;
290
291 case ID_CMD_MAPS_MOVE_UP:
292 if( Get_Manager()->Move_Up(this) )
293 ((CWKSP_Map *)Get_Manager())->View_Refresh(false);
294 break;
295
296 case ID_CMD_MAPS_MOVE_DOWN:
297 if( Get_Manager()->Move_Down(this) )
298 ((CWKSP_Map *)Get_Manager())->View_Refresh(false);
299 break;
300 }
301
302 return( true );
303 }
304
305 //---------------------------------------------------------
On_Command_UI(wxUpdateUIEvent & event)306 bool CWKSP_Map_BaseMap::On_Command_UI(wxUpdateUIEvent &event)
307 {
308 switch( event.GetId() )
309 {
310 default:
311 return( CWKSP_Base_Item::On_Command_UI(event) );
312
313 case ID_CMD_MAPS_LAYER_SHOW:
314 event.Check(m_bShow);
315 break;
316
317 case ID_CMD_MAPS_MOVE_TOP:
318 case ID_CMD_MAPS_MOVE_UP:
319 event.Enable(Get_Index() > 0);
320 break;
321
322 case ID_CMD_MAPS_MOVE_DOWN:
323 case ID_CMD_MAPS_MOVE_BOTTOM:
324 event.Enable(Get_Index() < Get_Manager()->Get_Count() - 1);
325 break;
326 }
327
328 return( true );
329 }
330
331
332 ///////////////////////////////////////////////////////////
333 // //
334 ///////////////////////////////////////////////////////////
335
336 //---------------------------------------------------------
On_Parameter_Changed(CSG_Parameters * pParameters,CSG_Parameter * pParameter,int Flags)337 int CWKSP_Map_BaseMap::On_Parameter_Changed(CSG_Parameters *pParameters, CSG_Parameter *pParameter, int Flags)
338 {
339 if( Flags & PARAMETER_CHECK_ENABLE )
340 {
341 if( pParameter->Cmp_Identifier("SHOW_ALWAYS") )
342 {
343 pParameters->Set_Enabled("SHOW_RANGE" , pParameter->asBool() == false);
344 }
345
346 if( pParameter->Cmp_Identifier("SERVER") )
347 {
348 pParameters->Set_Enabled("SERVER_USER", pParameter->asInt() >= pParameter->asChoice()->Get_Count() - 1); // user defined
349 }
350
351 if( pParameter->Cmp_Identifier("CACHE") )
352 {
353 pParameters->Set_Enabled("CACHE_DIR" , pParameter->asBool());
354 }
355 }
356
357 return( CWKSP_Base_Item::On_Parameter_Changed(pParameters, pParameter, Flags) );
358 }
359
360 //---------------------------------------------------------
Parameters_Changed(void)361 void CWKSP_Map_BaseMap::Parameters_Changed(void)
362 {
363 CWKSP_Base_Item::Parameters_Changed();
364
365 m_BaseMap.Destroy(); // forcing a base map refresh
366
367 Get_Map()->View_Refresh(true);
368 }
369
370
371 ///////////////////////////////////////////////////////////
372 // //
373 ///////////////////////////////////////////////////////////
374
375 //---------------------------------------------------------
Dlg_Parameters(void)376 bool CWKSP_Map_BaseMap::Dlg_Parameters(void)
377 {
378 m_Parameters("POSITION")->Set_Enabled(true);
379
380 bool bResult = DLG_Parameters(&m_Parameters);
381
382 m_Parameters("POSITION")->Set_Enabled(false);
383
384 return( bResult );
385 }
386
387
388 ///////////////////////////////////////////////////////////
389 // //
390 ///////////////////////////////////////////////////////////
391
392 //---------------------------------------------------------
Set_BaseMap(const CSG_Grid_System & System)393 bool CWKSP_Map_BaseMap::Set_BaseMap(const CSG_Grid_System &System)
394 {
395 CSG_Tool *pTool;
396
397 if( !Get_Map()->Get_Projection().is_Okay() || !(pTool = SG_Get_Tool_Library_Manager().Create_Tool("io_gdal", 9)) )
398 {
399 m_BaseMap.Destroy();
400
401 return( false );
402 }
403
404 SG_UI_ProgressAndMsg_Lock(true);
405
406 //-----------------------------------------------------
407 CSG_Grid BaseMap;
408
409 if( m_Parameters("RESOLUTION")->asDouble() > 1. )
410 {
411 BaseMap.Create(CSG_Grid_System(m_Parameters("RESOLUTION")->asDouble() * System.Get_Cellsize(), System.Get_Extent(true)), SG_DATATYPE_Int);
412 }
413 else
414 {
415 BaseMap.Create(System);
416 }
417
418 BaseMap.Get_Projection() = Get_Map()->Get_Projection();
419
420 m_pTool = pTool; // remember the last created base map tool instance
421
422 pTool->Set_Manager(NULL);
423
424 if( pTool->Set_Parameter("TARGET" , &BaseMap)
425 && pTool->Set_Parameter("TARGET_MAP" , &BaseMap)
426 && pTool->Set_Parameter("SERVER" , m_Parameters("SERVER" ))
427 && pTool->Set_Parameter("SERVER_USER", m_Parameters("SERVER_USER"))
428 && pTool->Set_Parameter("CACHE" , m_Parameters("CACHE" ))
429 && pTool->Set_Parameter("CACHE_DIR" , m_Parameters("CACHE_DIR" ))
430 && pTool->Set_Parameter("GRAYSCALE" , m_Parameters("GRAYSCALE" ))
431 && pTool->On_Before_Execution() && pTool->Execute() && pTool == m_pTool )
432 {
433 m_pTool = NULL;
434
435 m_BaseMap.Create(System, SG_DATATYPE_Int);
436
437 if( System == BaseMap.Get_System() )
438 {
439 #pragma omp parallel for
440 for(int i=0; i<m_BaseMap.Get_NCells(); i++)
441 {
442 m_BaseMap.Set_Value(i, BaseMap.asInt(i));
443 }
444 }
445 else
446 {
447 #pragma omp parallel for
448 for(int y=0; y<m_BaseMap.Get_NY(); y++) for(int x=0; x<m_BaseMap.Get_NX(); x++)
449 {
450 m_BaseMap.Set_Value(x, y, BaseMap.Get_Value(System.Get_Grid_to_World(x, y), GRID_RESAMPLING_BSpline, true));
451 }
452 }
453
454 if( m_Parameters("BRIGHTNESS")->asDouble() < 100. )
455 {
456 int Threshold = (int)(0.5 + 3 * 255 * m_Parameters("BRIGHTNESS")->asDouble() / 100.);
457
458 #pragma omp parallel for
459 for(int i=0; i<m_BaseMap.Get_NCells(); i++)
460 {
461 int c = m_BaseMap.asInt(i);
462
463 if( Threshold < (SG_GET_R(c) + SG_GET_G(c) + SG_GET_B(c)) )
464 {
465 m_BaseMap.Set_NoData(i);
466 }
467 }
468 }
469 }
470 else if( pTool == m_pTool )
471 {
472 m_pTool = NULL;
473
474 m_BaseMap.Destroy();
475 }
476
477 //-----------------------------------------------------
478 SG_UI_ProgressAndMsg_Lock(false);
479
480 SG_Get_Tool_Library_Manager().Delete_Tool(pTool);
481
482 return( m_BaseMap.is_Valid() );
483 }
484
485
486 ///////////////////////////////////////////////////////////
487 // //
488 ///////////////////////////////////////////////////////////
489
490 //---------------------------------------------------------
Draw(CWKSP_Map_DC & dc_Map)491 bool CWKSP_Map_BaseMap::Draw(CWKSP_Map_DC &dc_Map)
492 {
493 if( !m_Parameters("SHOW_ALWAYS")->asBool() )
494 {
495 CSG_Parameter_Range *pRange = m_Parameters("SHOW_RANGE")->asRange();
496 double dRange = dc_Map.m_rWorld.Get_XRange() > dc_Map.m_rWorld.Get_YRange() ? dc_Map.m_rWorld.Get_XRange() : dc_Map.m_rWorld.Get_YRange();
497
498 if( dRange < pRange->Get_Min() || pRange->Get_Max() < dRange )
499 {
500 return( false );
501 }
502 }
503
504 //-----------------------------------------------------
505 CSG_Grid_System System(dc_Map.m_DC2World, dc_Map.m_rWorld.Get_XMin(), dc_Map.m_rWorld.Get_YMin(), dc_Map.m_rDC.GetWidth(), dc_Map.m_rDC.GetHeight());
506
507 if( !System.is_Equal(m_BaseMap.Get_System()) && !Set_BaseMap(System) )
508 {
509 return( false );
510 }
511
512 //-----------------------------------------------------
513 if( dc_Map.IMG_Draw_Begin(m_Parameters("TRANSPARENCY")->asDouble() / 100.) )
514 {
515 #pragma omp parallel for
516 for(int y=0; y<m_BaseMap.Get_NY(); y++) for(int x=0, yy=m_BaseMap.Get_NY()-y-1; x<m_BaseMap.Get_NX(); x++)
517 {
518 if( !m_BaseMap.is_NoData(x, yy) )
519 {
520 dc_Map.IMG_Set_Pixel(x, y, m_BaseMap.asInt(x, yy));
521 }
522 }
523
524 dc_Map.IMG_Draw_End();
525 }
526
527 //-----------------------------------------------------
528 return( true );
529 }
530
531
532 ///////////////////////////////////////////////////////////
533 // //
534 // //
535 // //
536 ///////////////////////////////////////////////////////////
537
538 //---------------------------------------------------------
539