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