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