1 
2 ///////////////////////////////////////////////////////////
3 //                                                       //
4 //                         SAGA                          //
5 //                                                       //
6 //      System for Automated Geoscientific Analyses      //
7 //                                                       //
8 //           Application Programming Interface           //
9 //                                                       //
10 //                  Library: SAGA_API                    //
11 //                                                       //
12 //-------------------------------------------------------//
13 //                                                       //
14 //                     api_core.cpp                      //
15 //                                                       //
16 //          Copyright (C) 2005 by Olaf Conrad            //
17 //                                                       //
18 //-------------------------------------------------------//
19 //                                                       //
20 // This file is part of 'SAGA - System for Automated     //
21 // Geoscientific Analyses'.                              //
22 //                                                       //
23 // This library is free software; you can redistribute   //
24 // it and/or modify it under the terms of the GNU Lesser //
25 // General Public License as published by the Free       //
26 // Software Foundation, either version 2.1 of the        //
27 // License, or (at your option) any later version.       //
28 //                                                       //
29 // This library is distributed in the hope that it will  //
30 // be useful, but WITHOUT ANY WARRANTY; without even the //
31 // implied warranty of MERCHANTABILITY or FITNESS FOR A  //
32 // PARTICULAR PURPOSE. See the GNU Lesser General Public //
33 // License for more details.                             //
34 //                                                       //
35 // You should have received a copy of the GNU Lesser     //
36 // General Public License along with this program; if    //
37 // not, see <http://www.gnu.org/licenses/>.              //
38 //                                                       //
39 //-------------------------------------------------------//
40 //                                                       //
41 //    contact:    Olaf Conrad                            //
42 //                Institute of Geography                 //
43 //                University of Hamburg                  //
44 //                Germany                                //
45 //                                                       //
46 //    e-mail:     oconrad@saga-gis.org                   //
47 //                                                       //
48 ///////////////////////////////////////////////////////////
49 
50 //---------------------------------------------------------
51 #include <wx/utils.h>
52 #include <wx/app.h>
53 #include <wx/dir.h>
54 
55 #include "api_core.h"
56 #include "tool_library.h"
57 
58 
59 ///////////////////////////////////////////////////////////
60 //														 //
61 //														 //
62 //														 //
63 ///////////////////////////////////////////////////////////
64 
65 //---------------------------------------------------------
66 #ifdef _OPENMP
67 
68 #include <omp.h>
69 
70 //---------------------------------------------------------
71 int		g_SG_OMP_Max_Num_Threads	= omp_get_num_procs();
72 
73 //---------------------------------------------------------
SG_OMP_Set_Max_Num_Threads(int iCores)74 void	SG_OMP_Set_Max_Num_Threads	(int iCores)
75 {
76 	if( iCores < 1 )
77 	{
78 		iCores	= 1;
79 	}
80 	else if( iCores > omp_get_num_procs() )
81 	{
82 		iCores	= omp_get_num_procs();
83 	}
84 
85 	omp_set_num_threads(g_SG_OMP_Max_Num_Threads = iCores);
86 }
87 
88 //---------------------------------------------------------
SG_OMP_Get_Max_Num_Threads(void)89 int		SG_OMP_Get_Max_Num_Threads	(void)
90 {
91 	return( g_SG_OMP_Max_Num_Threads );
92 }
93 
94 //---------------------------------------------------------
SG_OMP_Get_Max_Num_Procs(void)95 int		SG_OMP_Get_Max_Num_Procs	(void)
96 {
97 	return( omp_get_num_procs() );
98 }
99 
100 //---------------------------------------------------------
SG_OMP_Get_Thread_Num(void)101 int		SG_OMP_Get_Thread_Num		(void)
102 {
103 	return( omp_get_thread_num() );
104 }
105 
106 //---------------------------------------------------------
107 #else
SG_OMP_Set_Max_Num_Threads(int iCores)108 void	SG_OMP_Set_Max_Num_Threads	(int iCores)	{}
SG_OMP_Get_Max_Num_Threads(void)109 int		SG_OMP_Get_Max_Num_Threads	(void)	{	return( 1 );	}
SG_OMP_Get_Max_Num_Procs(void)110 int		SG_OMP_Get_Max_Num_Procs	(void)	{	return( 1 );	}
SG_OMP_Get_Thread_Num(void)111 int		SG_OMP_Get_Thread_Num		(void)	{	return( 0 );	}
112 #endif
113 
114 
115 ///////////////////////////////////////////////////////////
116 //														 //
117 //														 //
118 //														 //
119 ///////////////////////////////////////////////////////////
120 
121 //---------------------------------------------------------
SG_Data_Type_Get_Name(TSG_Data_Type Type)122 CSG_String	SG_Data_Type_Get_Name	(TSG_Data_Type Type)
123 {
124 	switch( Type )
125 	{
126 	default                : return( _TL("undefined"                   ) );
127 	case SG_DATATYPE_Bit   : return( _TL("bit"                         ) );
128 	case SG_DATATYPE_Byte  : return( _TL("unsigned 1 byte integer"     ) );
129 	case SG_DATATYPE_Char  : return( _TL("signed 1 byte integer"       ) );
130 	case SG_DATATYPE_Word  : return( _TL("unsigned 2 byte integer"     ) );
131 	case SG_DATATYPE_Short : return( _TL("signed 2 byte integer"       ) );
132 	case SG_DATATYPE_DWord : return( _TL("unsigned 4 byte integer"     ) );
133 	case SG_DATATYPE_Int   : return( _TL("signed 4 byte integer"       ) );
134 	case SG_DATATYPE_ULong : return( _TL("unsigned 8 byte integer"     ) );
135 	case SG_DATATYPE_Long  : return( _TL("signed 8 byte integer"       ) );
136 	case SG_DATATYPE_Float : return( _TL("4 byte floating point number") );
137 	case SG_DATATYPE_Double: return( _TL("8 byte floating point number") );
138 	case SG_DATATYPE_String: return( _TL("string"                      ) );
139 	case SG_DATATYPE_Date  : return( _TL("date"                        ) );
140 	case SG_DATATYPE_Color : return( _TL("color"                       ) );
141 	case SG_DATATYPE_Binary: return( _TL("binary"                      ) );
142 	}
143 };
144 
145 //---------------------------------------------------------
SG_Data_Type_Get_Identifier(TSG_Data_Type Type)146 CSG_String	SG_Data_Type_Get_Identifier	(TSG_Data_Type Type)
147 {
148 	return( gSG_Data_Type_Identifier[Type] );
149 }
150 
151 //---------------------------------------------------------
SG_Data_Type_Get_Type(const CSG_String & Identifier)152 TSG_Data_Type SG_Data_Type_Get_Type(const CSG_String &Identifier)
153 {
154 	if( !Identifier.Cmp(gSG_Data_Type_Identifier[SG_DATATYPE_Bit   ]) )	return( SG_DATATYPE_Bit    );
155 	if( !Identifier.Cmp(gSG_Data_Type_Identifier[SG_DATATYPE_Byte  ]) )	return( SG_DATATYPE_Byte   );
156 	if( !Identifier.Cmp(gSG_Data_Type_Identifier[SG_DATATYPE_Char  ]) )	return( SG_DATATYPE_Char   );
157 	if( !Identifier.Cmp(gSG_Data_Type_Identifier[SG_DATATYPE_Word  ]) )	return( SG_DATATYPE_Word   );
158 	if( !Identifier.Cmp(gSG_Data_Type_Identifier[SG_DATATYPE_Short ]) )	return( SG_DATATYPE_Short  );
159 	if( !Identifier.Cmp(gSG_Data_Type_Identifier[SG_DATATYPE_DWord ]) )	return( SG_DATATYPE_DWord  );
160 	if( !Identifier.Cmp(gSG_Data_Type_Identifier[SG_DATATYPE_Int   ]) )	return( SG_DATATYPE_Int    );
161 	if( !Identifier.Cmp(gSG_Data_Type_Identifier[SG_DATATYPE_ULong ]) )	return( SG_DATATYPE_ULong  );
162 	if( !Identifier.Cmp(gSG_Data_Type_Identifier[SG_DATATYPE_Long  ]) )	return( SG_DATATYPE_Long   );
163 	if( !Identifier.Cmp(gSG_Data_Type_Identifier[SG_DATATYPE_Float ]) )	return( SG_DATATYPE_Float  );
164 	if( !Identifier.Cmp(gSG_Data_Type_Identifier[SG_DATATYPE_Double]) )	return( SG_DATATYPE_Double );
165 	if( !Identifier.Cmp(gSG_Data_Type_Identifier[SG_DATATYPE_String]) )	return( SG_DATATYPE_String );
166 	if( !Identifier.Cmp(gSG_Data_Type_Identifier[SG_DATATYPE_Date  ]) )	return( SG_DATATYPE_Date   );
167 	if( !Identifier.Cmp(gSG_Data_Type_Identifier[SG_DATATYPE_Color ]) )	return( SG_DATATYPE_Color  );
168 
169 	return( SG_DATATYPE_Undefined );
170 }
171 
172 //---------------------------------------------------------
SG_Data_Type_is_Numeric(TSG_Data_Type Type)173 bool SG_Data_Type_is_Numeric(TSG_Data_Type Type)
174 {
175 	switch( Type )
176 	{
177 	case SG_DATATYPE_Bit   :
178 	case SG_DATATYPE_Byte  :
179 	case SG_DATATYPE_Char  :
180 	case SG_DATATYPE_Word  :
181 	case SG_DATATYPE_Short :
182 	case SG_DATATYPE_DWord :
183 	case SG_DATATYPE_Int   :
184 	case SG_DATATYPE_ULong :
185 	case SG_DATATYPE_Long  :
186 	case SG_DATATYPE_Float :
187 	case SG_DATATYPE_Double:
188 		return( true );
189 
190 	case SG_DATATYPE_String:
191 	case SG_DATATYPE_Date  :
192 	case SG_DATATYPE_Color :
193 	case SG_DATATYPE_Binary: default:
194 		return( false );
195 	}
196 }
197 
198 //---------------------------------------------------------
SG_Data_Type_Range_Check(TSG_Data_Type Type,double & Value)199 bool SG_Data_Type_Range_Check(TSG_Data_Type Type, double &Value)
200 {
201 	double	min, max;
202 
203 	switch( Type )
204 	{
205 		default:
206 		case SG_DATATYPE_Double: Value = (double)Value; return( true );
207 		case SG_DATATYPE_Float : Value = (float )Value; return( true );
208 
209 		case SG_DATATYPE_Bit   : min =           0.; max =          1.; break;
210 		case SG_DATATYPE_Byte  : min =           0.; max =        255.; break;
211 		case SG_DATATYPE_Char  : min =        -128.; max =        127.; break;
212 		case SG_DATATYPE_Word  : min =           0.; max =      65535.; break;
213 		case SG_DATATYPE_Short : min =      -32768.; max =      32767.; break;
214 		case SG_DATATYPE_DWord : min =           0.; max = 4294967295.; break;
215 		case SG_DATATYPE_Int   : min = -2147483648.; max = 2147483647.; break;
216 	}
217 
218 	if( Value < min )
219 	{
220 		Value	= min;
221 	}
222 	else if( Value > max )
223 	{
224 		Value	= max;
225 	}
226 
227 	return( true );
228 }
229 
230 
231 ///////////////////////////////////////////////////////////
232 //														 //
233 //                     Environment                       //
234 //														 //
235 ///////////////////////////////////////////////////////////
236 
237 //---------------------------------------------------------
238 /**
239 * This class is for internal use only. It has a single instance
240 * (g_App_Initialize) that is used to make a call to wxInitialize()
241 * when SG_Initialize_Environment() is called with bInitializeWX = true
242 * (default) to ensure wxWidgets is fully working, even if SAGA API
243 * is used outside of SAGA's GUI or CMD (i.e. from Python).
244 * You might want to call SG_Uninitialize_Environment() before you
245 * exit your application to invoke wxUninitialize(),
246 * what is suggested to be done by wxWidgets documentation.
247 */
248 class CSG_App_Initialize
249 {
250 public:
CSG_App_Initialize(void)251 	CSG_App_Initialize(void)
252 	{
253 		m_Initialized	= 0;
254 	}
255 
~CSG_App_Initialize(void)256 	virtual ~CSG_App_Initialize(void)
257 	{}
258 
Initialize(void)259 	bool	Initialize		(void)
260 	{
261 		if( wxInitialize() )
262 		{
263 			m_Initialized++;
264 
265 			return( true );
266 		}
267 
268 		return( false );
269 	}
270 
Uninitialize(void)271 	bool	Uninitialize	(void)
272 	{
273 		if( m_Initialized > 0 )
274 		{
275 			wxUninitialize();
276 
277 			m_Initialized--;
278 
279 			return( true );
280 		}
281 
282 		return( false );
283 	}
284 
Uninitialize(bool bAll)285 	bool	Uninitialize	(bool bAll)
286 	{
287 		if( bAll )
288 		{
289 			while( m_Initialized > 0 )
290 			{
291 				Uninitialize();
292 			}
293 		}
294 		else
295 		{
296 			Uninitialize();
297 		}
298 
299 		return( true );
300 	}
301 
302 
303 private:
304 
305 	int		m_Initialized;
306 
307 };
308 
309 //---------------------------------------------------------
310 CSG_App_Initialize	g_App_Initialize;
311 
312 
313 ///////////////////////////////////////////////////////////
314 //														 //
315 ///////////////////////////////////////////////////////////
316 
317 //---------------------------------------------------------
SG_Add_Dll_Paths(const wxString & Directory,wxString & Paths)318 bool SG_Add_Dll_Paths(const wxString &Directory, wxString &Paths)
319 {
320 	wxDir	Dir(Directory);
321 
322 	if( Dir.IsOpened() )
323 	{
324 		wxString	Path;
325 
326 		if( Dir.GetFirst(&Path, "*.dll", wxDIR_HIDDEN|wxDIR_FILES) )
327 		{
328 			if( !Path.IsEmpty() )
329 			{
330 				Paths	+= ";";
331 			}
332 
333 			Paths	+= Directory;
334 		}
335 
336 		if( Dir.GetFirst(&Path, "gdal_netCDF.dll", wxDIR_HIDDEN|wxDIR_FILES) )
337 		{
338 			wxSetEnv("GDAL_DRIVER_PATH", Directory);
339 		}
340 
341 		if( Dir.GetFirst(&Path, wxEmptyString, wxDIR_HIDDEN|wxDIR_DIRS) )
342 		{
343 			do
344 			{
345 				wxString	SubDir(Directory + "\\" + Path);
346 
347 				if(      !Path.CmpNoCase("gdal-plugins") ) { wxSetEnv("GDAL_DRIVER_PATH", SubDir); }
348 				else if( !Path.CmpNoCase("gdal-data"   ) ) { wxSetEnv("GDAL_DATA"       , SubDir); }
349 				else if( !Path.CmpNoCase("proj-data"   ) ) { wxSetEnv("PROJ_LIB"        , SubDir); }
350 				else
351 				{
352 					SG_Add_Dll_Paths(SubDir, Paths);
353 				}
354 			}
355 			while( Dir.GetNext(&Path) );
356 		}
357 	}
358 
359 	return( !Paths.IsEmpty() );
360 }
361 
362 //---------------------------------------------------------
SG_Initialize_Environment(bool bLibraries,bool bProjections,const SG_Char * Directory,bool bInitializeWX)363 bool SG_Initialize_Environment(bool bLibraries, bool bProjections, const SG_Char *Directory, bool bInitializeWX)
364 {
365 	if( bInitializeWX )
366 	{
367 		g_App_Initialize.Initialize();
368 	}
369 
370 	SG_UI_ProgressAndMsg_Lock(true);
371 
372 	//-----------------------------------------------------
373 	#ifdef _SAGA_MSW
374 	{
375 		wxString App_Path, Dll_Paths, System_Paths;
376 
377 		if( Directory && SG_Dir_Exists(Directory) )
378 		{
379 			App_Path	= Directory;
380 		}
381 		else
382 		{
383 			App_Path	= SG_UI_Get_Application_Path(true).c_str();
384 		}
385 
386         wxGetEnv("PATH", &System_Paths);
387 
388 		if( SG_Add_Dll_Paths(App_Path + "\\dll", Dll_Paths) )
389 		{
390             Dll_Paths   += ';' + App_Path + ';' + System_Paths;
391 
392 			wxSetEnv("PATH", Dll_Paths);
393 		}
394 
395 		if( bLibraries )
396 		{
397 			SG_Get_Tool_Library_Manager().Add_Directory(SG_File_Make_Path(&App_Path, "tools"), false);
398 		}
399 
400 		if( bProjections )
401 		{
402 			SG_Get_Projections().Load_Dictionary(SG_File_Make_Path(&App_Path, "saga_prj", "dic"));
403 			SG_Get_Projections().Load_DB        (SG_File_Make_Path(&App_Path, "saga_prj", "srs"));
404 		}
405 	}
406 	#else // #ifdef _SAGA_LINUX
407 	{
408 		if( bLibraries )
409 		{
410 			SG_Get_Tool_Library_Manager().Add_Directory(TOOLS_PATH);
411 			SG_Get_Tool_Library_Manager().Add_Directory(SG_File_Make_Path(SHARE_PATH, "toolchains"));	// look for tool chains
412 		}
413 
414 		if( bProjections )
415 		{
416 			SG_Get_Projections().Load_Dictionary(SG_File_Make_Path(SHARE_PATH, "saga_prj", "dic"));
417 			SG_Get_Projections().Load_DB        (SG_File_Make_Path(SHARE_PATH, "saga_prj", "srs"));
418 		}
419 	}
420 	#endif
421 
422 	//-----------------------------------------------------
423 	if( bLibraries )
424 	{
425 		wxString Path;
426 
427 		if( wxGetEnv("SAGA_TLB", &Path) )
428 		{
429 			#ifdef _SAGA_MSW
430 				CSG_Strings	Paths = SG_String_Tokenize(&Path, ";" ); // colon (':') would split drive from paths!
431 			#else // #ifdef _SAGA_LINUX
432 				CSG_Strings	Paths = SG_String_Tokenize(&Path, ";:"); // colon (':') is more native to non-windows os than semi-colon (';'), we support both...
433 			#endif
434 
435 			for(int i=0; i<Paths.Get_Count(); i++)
436 			{
437 				SG_Get_Tool_Library_Manager().Add_Directory(Paths[i]);
438 			}
439 		}
440 	}
441 
442 	//-----------------------------------------------------
443 	SG_UI_ProgressAndMsg_Lock(false);
444 
445 	return( true );
446 }
447 
448 //---------------------------------------------------------
SG_Uninitialize_Environment(void)449 bool SG_Uninitialize_Environment(void)
450 {
451 	g_App_Initialize.Uninitialize(true);
452 
453 	return( true );
454 }
455 
456 
457 ///////////////////////////////////////////////////////////
458 //														 //
459 //														 //
460 //														 //
461 ///////////////////////////////////////////////////////////
462 
463 //---------------------------------------------------------
464