source: trunk/zoo-project/zoo-kernel/service_internal_saga.c @ 634

Last change on this file since 634 was 634, checked in by djay, 9 years ago

Integrate a basic SAGA-GIS support into the ZOO-Kernel.

  • Property svn:keywords set to Id
File size: 34.1 KB
Line 
1/*
2 * Author : Gérald FENOY
3 *
4 * Copyright (c) 2015 GeoLabs SARL
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24
25#include <stdlib.h>
26#include <limits.h>
27#include "service_internal_saga.h"
28#include "mimetypes.h"
29
30/**
31 * Observer used to access the ongoing status of a running OTB Application
32 */
33class SagaWatcher
34{
35 public:
36  static int Callback(TSG_UI_Callback_ID ID, CSG_UI_Parameter &Param_1, CSG_UI_Parameter &Param_2);
37  //int Callback(TSG_UI_Callback_ID ID, CSG_UI_Parameter &Param_1, CSG_UI_Parameter &Param_2);
38  /**
39   * Define the message value
40   *
41   * @param conf the maps pointer to copy
42   */
43  static void SetMessage(const char *mess)
44  {
45    FreeMessage();
46    message=zStrdup(mess);
47  }
48  /**
49   * Free the message value
50   *
51   */
52  static void FreeMessage()
53  {
54    if(message!=NULL)
55      free(message);
56    message=NULL;
57  }
58  /**
59   * Copy the original conf in the m_conf property
60   *
61   * @param conf the maps pointer to copy
62   */
63  void SetConf(maps **conf)
64  {
65    m_conf=dupMaps(conf);
66  }
67  /** 
68   * Get Configuration maps (m_conf)
69   * @return the m_conf property
70   */
71  const maps& GetConf()
72  {
73    return *m_conf;
74  }
75  /** 
76   * Free Configuration maps (m_Conf)
77   */
78  void FreeConf(){
79    freeMaps(&m_conf);
80    free(m_conf);
81  }
82 private:
83  /** Main conf maps */
84  static maps* m_conf;
85  /** Status */
86  static int status;
87  /** Message */
88  static char* message;
89};
90
91maps* SagaWatcher::m_conf;
92char* SagaWatcher::message=zStrdup("");
93int SagaWatcher::status=1;
94
95/**
96 * The callback function called at any SAGA-GIS module step
97 *
98 * @param id a TSG_UI_Callback_ID as defined in api_core.h (line 1290)
99 * @param param1
100 * @param param2
101 */
102int
103SagaWatcher::
104Callback(TSG_UI_Callback_ID id, CSG_UI_Parameter &param1, CSG_UI_Parameter &param2)
105{
106
107  int res = 1;
108  switch( id )
109    {
110    default:
111      res = 0;
112      break;
113
114    case CALLBACK_PROCESS_GET_OKAY:
115      break;
116
117    case CALLBACK_PROCESS_SET_OKAY:
118      break;
119
120    case CALLBACK_PROCESS_SET_PROGRESS:
121      {
122        int cPercent= param2.Number != 0.0 ? 1 + (int)(100.0 * param1.Number / param2.Number) : 100 ;
123        if( cPercent != status ){
124          status=cPercent;
125        }
126      }
127      break;
128
129    case CALLBACK_PROCESS_SET_READY:
130      status=1;
131      break;
132
133    case CALLBACK_PROCESS_SET_TEXT:
134      SetMessage(param1.String.b_str());
135      break;
136
137    case CALLBACK_MESSAGE_ADD:
138      SetMessage(param1.String.b_str());
139      break;
140
141    case CALLBACK_MESSAGE_ADD_ERROR:
142      SetMessage(param1.String.b_str());
143      break;
144
145    case CALLBACK_MESSAGE_ADD_EXECUTION:
146      SetMessage(param1.String.b_str());
147      break;
148
149    case CALLBACK_DLG_MESSAGE:
150      SetMessage((param2.String + ": " + param1.String).b_str());
151      break;
152
153    case CALLBACK_DLG_CONTINUE:
154      break;
155
156    case CALLBACK_DLG_ERROR:
157      break;
158
159    case CALLBACK_DATAOBJECT_ADD:
160      if(SG_Get_Data_Manager().Add((CSG_Data_Object *)param1.Pointer))
161        res = 1 ;
162      else
163        res = 0;
164      break;
165
166    case CALLBACK_DATAOBJECT_UPDATE:
167      break;
168
169    case CALLBACK_DATAOBJECT_SHOW:
170      break;
171
172    case CALLBACK_DATAOBJECT_COLORS_GET:
173      break;
174
175    case CALLBACK_DATAOBJECT_COLORS_SET:
176      break;
177
178    case CALLBACK_DATAOBJECT_PARAMS_GET:
179      break;
180
181    case CALLBACK_DATAOBJECT_PARAMS_SET:
182      break;
183
184    case CALLBACK_DLG_PARAMETERS:
185      break;
186
187    }
188  updateStatus(m_conf,status,message);
189  return( res );
190}
191
192TSG_PFNC_UI_Callback    Get_Callback    (SagaWatcher watcher)
193{
194  return( &(watcher.Callback) );
195}
196
197
198/**
199 * Get the default file extension for SAGA-GIS parameter type.
200 * Extensions are the following:
201 *  - sgrd for grid and data_object
202 *  - shp for shapes and tin
203 *  - csv for tables
204 *  - spc for points
205 *
206 * @param param a SAGA-GIS Parameter
207 */ 
208const char* sagaGetDefaultExt(CSG_Parameter* param){
209  if(CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("grid"))
210     || CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("data_object"))){
211    return "sgrd";
212  }
213  else if(CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("shapes")) ||
214          CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("tin"))){
215    return "shp";
216  }
217  else if(CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("table"))){
218    return "csv";
219  }
220  else if(CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("points"))){
221    return "spc";
222  }
223  return "unknown";
224}
225
226/**
227 * Load a datasource in the SAGA-GIS Data Manager.
228 *
229 * @param param a SAGA-GIS Parameter
230 * @param arg the arguments map passed to a SAGA-GIS module
231 * @return false on failure, true in case of success
232 */
233bool sagaLoadInput(CSG_Parameter* param,map* arg){
234  if(!param->is_Input() || !param->is_Enabled()){
235    return true;
236  }
237  map* carg=getMap(arg,CSG_String(param->Get_Identifier()).b_str());
238  if(carg!=NULL){
239    wxString fileName(carg->value);
240    if(param->is_DataObject()){
241      // In case it there is a single datasource
242      if(!SG_Get_Data_Manager().Find(&fileName) && !SG_Get_Data_Manager().Add(&fileName) && !param->is_Optional() ){
243        return false;
244      }
245      return( param->Set_Value(SG_Get_Data_Manager().Find(&fileName)) );
246    }
247    else
248      if(param->is_DataObject_List()){
249        // In case there are multiple datasources
250        param->asList()->Del_Items();
251        wxString fileNames(fileName);
252        while( fileNames.Length() > 0 ){
253          fileName = fileNames.BeforeFirst(';').Trim(false);
254          fileNames = fileNames.AfterFirst (';');           
255          if( !SG_Get_Data_Manager().Find(&fileName) ){
256            SG_Get_Data_Manager().Add(&fileName);
257          }
258          param->asList()->Add_Item(SG_Get_Data_Manager().Find(&fileName));
259        }
260      }
261  }
262  return true;
263}
264
265/**
266 * Extract all SAGA-GIS parameters from a parameters list and set its values to
267 * the one defined in the map.
268 *
269 * @parap params the parameters list
270 * @parap argument the argument map containing the value to use
271 * @return true in success, false in other case
272 */
273bool sagaSetParameters(CSG_Parameters *params,map* argument){
274
275  int pc=params->Get_Count();
276  params->Restore_Defaults();
277
278  for(int k=0;k<pc;k++){
279    CSG_Parameter * param=params->Get_Parameter(k);
280    if( param->is_Output() ){
281      map* omap=getMap(argument,CSG_String(param->Get_Identifier()).b_str());
282      if( param->is_DataObject() && param->is_Optional() && !param->asDataObject() && omap!=NULL){
283        param->Set_Value(DATAOBJECT_CREATE);
284      }
285    }
286    else
287      if( param->is_Option() && !param->is_Information() ){
288        map* inmap=getMap(argument,CSG_String(param->Get_Identifier()).b_str());
289        if(inmap!=NULL){
290            switch( param->Get_Type() ){
291            case PARAMETER_TYPE_Bool:
292              if(strncasecmp(inmap->value,"true",4)==0 || strncasecmp(inmap->value,"1",1)==0){
293                param->Set_Value(1);
294              }else
295                param->Set_Value(0);
296              break;
297            case PARAMETER_TYPE_Parameters:
298              // TODO: nested inputs gesture
299              break;
300            case PARAMETER_TYPE_Int:
301              param->Set_Value((int)strtol(inmap->value,NULL,10));
302              break;
303            case PARAMETER_TYPE_Double:
304            case PARAMETER_TYPE_Degree:
305              param->Set_Value((double)strtod(inmap->value,NULL));
306              break;
307            case PARAMETER_TYPE_String:
308              param->Set_Value(CSG_String(inmap->value));
309              break;
310            case PARAMETER_TYPE_FilePath:
311              param->Set_Value(CSG_String(inmap->value));
312              break;
313            case PARAMETER_TYPE_FixedTable:
314              {
315                CSG_Table Table(inmap->value);
316                param->asTable()->Assign_Values(&Table);
317              }
318              break;
319            case PARAMETER_TYPE_Choice:
320              {
321                int val=(int)strtol(inmap->value,(char**)NULL,10);
322                if(val==0 && strncasecmp(inmap->value,"0",1)!=0)
323                  param->Set_Value(CSG_String(inmap->value));
324                else
325                  param->Set_Value(val);
326              }
327              break;
328            default:
329              break;
330            }
331        }else{
332          if(param->Get_Type()==PARAMETER_TYPE_Range){
333            inmap=getMap(argument,(CSG_String(param->Get_Identifier())+"_MIN").b_str());
334            if(inmap!=NULL)
335              param->asRange()->Set_LoVal(strtod(inmap->value,NULL));
336            inmap=getMap(argument,(CSG_String(param->Get_Identifier())+"_MAX").b_str());
337            if(inmap!=NULL)
338              param->asRange()->Set_HiVal(strtod(inmap->value,NULL));       
339          }
340          if(inmap==NULL){
341            param->Restore_Default();
342          }
343        }
344      }
345  }
346
347  for(int k=0;k<pc;k++){
348    CSG_Parameter * param=params->Get_Parameter(k);
349    if( param->is_Input() )
350      if(!sagaLoadInput(param,argument)){
351        fprintf(stderr,"%s %d \n",__FILE__,__LINE__);
352        return false;
353      }
354  }
355  return true;
356}
357
358/**
359 * Save all values outputed by a SAGA-GIS module invocation to files
360 *
361 * @param params the parameters list
362 * @param main_conf the conf maps containing the main.cfg settings
363 * @param outputs the maps to set the generated_file for each output
364 */
365bool sagaSaveOutputs(CSG_Parameters *params,maps* main_conf,maps** outputs)
366{
367  for(int j=0; j<params->Get_Count(); j++)
368    {
369      CSG_Parameter *param = params->Get_Parameter(j);
370      maps* cMaps=getMaps(*outputs,CSG_String(param->Get_Identifier()).b_str());
371      // Specific TIN case
372      if(cMaps==NULL && CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("tin")))
373        cMaps=getMaps(*outputs,(CSG_String(param->Get_Identifier())+"_POINTS").b_str());
374      if(cMaps!=NULL){
375        map* tmpPath=getMapFromMaps(main_conf,"main","tmpPath");
376        map* sid=getMapFromMaps(main_conf,"lenv","usid");
377        const char *file_ext=sagaGetDefaultExt(param);
378
379        if( param->is_Input() )
380          {
381            if( param->is_DataObject() )
382              {
383                CSG_Data_Object *pObject = param->asDataObject();
384               
385                if( pObject && pObject->is_Modified() && SG_File_Exists(pObject->Get_File_Name()) )
386                  {
387                    pObject->Save(pObject->Get_File_Name());
388                    addToMap(cMaps->content,"generated_file",CSG_String(pObject->Get_File_Name()).b_str());
389                  }
390              }
391           
392            else if( param->is_DataObject_List() )
393              {
394                for(int i=0; i<param->asList()->Get_Count(); i++)
395                  {
396                    CSG_Data_Object     *pObject        = param->asList()->asDataObject(i);
397                   
398                    if( pObject->is_Modified() && SG_File_Exists(pObject->Get_File_Name()) )
399                      {
400                        pObject->Save(pObject->Get_File_Name());
401                        setMapArray(cMaps->content,"generated_file",i,CSG_String(pObject->Get_File_Name()).b_str());
402                      }
403                  }
404              }
405          }
406        else
407          if( param->is_Output() )
408            {
409              char *realFileName=(char*)malloc((strlen(file_ext)+strlen(sid->value)+strlen(cMaps->name)+14)*sizeof(char));
410              char *fullFileName=(char*)malloc((strlen(file_ext)+strlen(sid->value)+strlen(cMaps->name)+strlen(tmpPath->value)+16)*sizeof(char));
411              sprintf(realFileName,"Output_%s_%d_%s",cMaps->name,sagaOutputCounter,sid->value);
412              sprintf(fullFileName,"%s/Output_%s_%d_%s.%s",tmpPath->value,cMaps->name,sagaOutputCounter,sid->value,file_ext);
413              sagaOutputCounter+=1;
414              wxString fileName(fullFileName);
415              addToMap(cMaps->content,"generated_name",realFileName);
416              free(realFileName);
417              free(fullFileName);
418
419              if( param->is_DataObject() )
420                {
421                  if( param->asDataObject() )
422                    {
423                      param->asDataObject()->Save(&fileName);
424                      addToMap(cMaps->content,"generated_file",CSG_String(param->asDataObject()->Get_File_Name()).b_str());
425                    }
426                }
427           
428              else if( param->is_DataObject_List() )
429                {
430                  CSG_Strings   fileNames;
431               
432                  while( fileName.Length() > 0 )
433                    {
434                      CSG_String        s(&fileName); s = s.BeforeFirst(';');
435                   
436                      if( s.Length() > 0 )
437                        {
438                          fileNames     += s;
439                          fileName       = fileName.AfterFirst(';');
440                        }
441                      else
442                        {
443                          fileNames     += &fileName;
444                          fileName      .Clear();
445                        }
446                    }
447               
448                  int nFileNames = param->asList()->Get_Count() <= fileNames.Get_Count() ? fileNames.Get_Count() : fileNames.Get_Count() - 1;
449                  for(int i=0; i<param->asList()->Get_Count(); i++)
450                    {
451                      fileNames[i].Trim();
452                      if( i < nFileNames )
453                        {
454                          param->asList()->asDataObject(i)->Save(fileNames[i]);
455                        }
456                      else
457                        {
458                          param->asList()->asDataObject(i)->Save(CSG_String::Format(SG_T("%s_%0*d"),
459                                                                                    fileNames[fileNames.Get_Count() - 1].c_str(),
460                                                                                    SG_Get_Digit_Count(param->asList()->Get_Count()),
461                                                                                    1 + i - nFileNames
462                                                                                    ));
463                        }
464                      setMapArray(cMaps->content,"generated_file",i,
465                                  CSG_String(param->asList()->asDataObject(i)->Get_File_Name()).b_str());
466                    }
467                }
468            }
469      }
470    } 
471  return( true );
472}
473
474/**
475 * Invoke the execution of a SAGA-GIS module.
476 *
477 * @param main_conf the conf maps containing the main.cfg settings
478 * @param lib_name the SAGA-GIS library name
479 * @param module_name the SAGA-GIS module name
480 * @param arguments the map containing the arguments to pass to the module
481 * @param outputs default to NULL, contains the maps to fill with the result
482 */
483int sagaExecuteCmd(maps** main_conf,const char* lib_name,const char* module_name,map* arguments,maps** outputs=NULL){
484  int res=SERVICE_FAILED;
485
486  CSG_Module_Library * library=SG_Get_Module_Library_Manager().Get_Library(CSG_String(lib_name),true);
487  if( library == NULL){
488    char tmp[255];
489    sprintf(tmp,"Counld not load the %s SAGA library",lib_name);
490    setMapInMaps(*main_conf,"lenv","message",tmp);
491    res=SERVICE_FAILED;
492    return res;
493  }
494
495  CSG_Module * module=library->Get_Module(atoi(module_name));
496  if(module == NULL){
497    char tmp[255];
498    sprintf(tmp,"Counld not load the %s module from the %s SAGA library",module_name,lib_name);
499    setMapInMaps(*main_conf,"lenv","message",tmp);
500    res=SERVICE_FAILED;
501    return res;
502  }
503
504  CSG_Parameters * params=module->Get_Parameters();
505  if(!params){
506    char tmp[255];
507    sprintf(tmp,"Counld not find any param for the %s module from the %s SAGA library",module_name,lib_name);
508    setMapInMaps(*main_conf,"lenv","message",tmp);
509    res=SERVICE_FAILED;
510    return res;
511  }
512 
513  sagaSetParameters(params,arguments);
514
515  module->Update_Parameter_States();
516
517  bool retval=false;
518  if(module->On_Before_Execution()){
519    retval=module->Execute();
520    module->On_After_Execution();
521  }
522 
523  if(retval && outputs!=NULL){
524    sagaSaveOutputs(module->Get_Parameters(),*main_conf,outputs);
525    SG_Get_Data_Manager().Delete_Unsaved();
526    return SERVICE_SUCCEEDED;
527  }
528
529  return SERVICE_FAILED;
530
531}
532
533/**
534 * Export a SAGA-GIS Shapes to a file in a specific format (GML,KML,GeoJSON).
535 * saga_cmd io_gdal 4 -FILE my.format -SHAPES my.shp -FORMAT XXX
536 *
537 * @param main_conf the conf maps containing the main.cfg settings
538 * @param in the output maps to fill with the resulting file
539 */
540int sagaExportOGR(maps** conf, maps** in){
541  map* mtype=getMap((*in)->content,"mimeType");
542  map* gfile=getMap((*in)->content,"generated_file");
543  char* fext=NULL;
544  map* arg=NULL;
545  if(strncasecmp(mtype->value,"text/xml",8)==0){
546    fext=zStrdup("xml");
547  }
548  else if(strncasecmp(mtype->value,"application/json",16)==0){
549    fext=zStrdup("json");
550  }
551  else{
552    fext=zStrdup("kml");
553  }
554  char* tmpName=(char*)malloc((strlen(gfile->value)+2)*sizeof(char));
555  strncpy(tmpName,gfile->value,(strlen(gfile->value)-3)*sizeof(char));
556  strncpy(&tmpName[0]+(strlen(gfile->value)-3),fext,(strlen(fext))*sizeof(char));
557  tmpName[strlen(fext)+(strlen(gfile->value)-3)]=0;
558  arg=createMap("SHAPES",gfile->value);
559  addToMap(arg,"FILE",tmpName);
560  if(strncasecmp(mtype->value,"text/xml",8)==0){
561    addToMap(arg,"FORMAT","GML");
562  }
563  else if(strncasecmp(mtype->value,"application/json",16)==0){
564    addToMap(arg,"FORMAT","GeoJSON");
565  }
566  else{
567    addToMap(arg,"FORMAT","LIBKML");
568  }
569  free(fext);
570  free(gfile->value);
571  gfile->value=zStrdup(tmpName);
572  free(tmpName);
573 
574  sagaExecuteCmd(conf,"io_gdal","4",arg);
575  freeMap(&arg);
576  free(arg);
577}
578
579/**
580 * Export a SAGA-GIS pointcloud to a las file.
581 * saga_cmd io_shapes_las 0 -POINTS my.spc -FILE my.las
582 *
583 * @param main_conf the conf maps containing the main.cfg settings
584 * @param in the output maps to fill with the resulting file
585 */
586void sagaExportPC(maps** conf, maps** in){
587  map* mtype=getMap((*in)->content,"mimeType");
588  map* gfile=getMap((*in)->content,"generated_file");
589  char* fext="las";
590  map* arg=NULL;
591  char* tmpName=(char*)malloc((strlen(gfile->value)+2)*sizeof(char));
592  strncpy(tmpName,gfile->value,(strlen(gfile->value)-3)*sizeof(char));
593  strncpy(&tmpName[0]+(strlen(gfile->value)-3),fext,(strlen(fext))*sizeof(char));
594  tmpName[strlen(fext)+(strlen(gfile->value)-3)]=0;
595  arg=createMap("POINTS",gfile->value);
596  addToMap(arg,"FILE",tmpName);
597  free(gfile->value);
598  gfile->value=zStrdup(tmpName);
599  sagaExecuteCmd(conf,"io_shapes_las","0",arg);
600  freeMap(&arg);
601  free(arg);
602  free(tmpName);
603}
604
605/**
606 * Export a SAGA-GIS Grid to a file in a specific format (tiff,hdr,aa).
607 * saga_cmd io_gdal 1 -FILE my.format -GRIDS my.sgrd -FORMAT XXX
608 *
609 * @param main_conf the conf maps containing the main.cfg settings
610 * @param in the output maps to fill with the resulting file
611 */
612int sagaExportGDAL(maps** conf, maps** in/*,CSG_Parameter* param*/){
613  map* mtype=getMap((*in)->content,"extension");
614  map* gfile=getMap((*in)->content,"generated_file");
615  char* fext=NULL;
616  map* arg;
617
618  if(mtype!=NULL)
619    fext=zStrdup(mtype->value);
620  else{
621    fext=zStrdup("tiff");
622  }
623
624  mtype=getMap((*in)->content,"mimeType");
625  if(strncasecmp(mtype->value,"image/tiff",10)==0){
626    arg=createMap("FORMAT","1");
627  }
628  else if(strncasecmp(mtype->value,"application/x-ogc-envi",22)==0){
629    arg=createMap("FORMAT","ENVI .hdr Labelled");
630  }
631  else{
632    arg=createMap("FORMAT","ARC Digitized Raster Graphics");
633  }
634
635  if(gfile!=NULL){
636    char* tmpName=(char*)malloc((strlen(gfile->value)+1)*sizeof(char));
637    strncpy(tmpName,gfile->value,(strlen(gfile->value)-4)*sizeof(char));
638    strncpy(&tmpName[0]+(strlen(gfile->value)-4),fext,(strlen(fext))*sizeof(char));
639    tmpName[strlen(fext)+(strlen(gfile->value)-4)]=0;
640    addToMap(arg,"FILE",tmpName);
641    addToMap(arg,"GRIDS",gfile->value);
642    free(tmpName);
643    free(fext);
644    free(gfile->value);
645    map* tmp=getMap(arg,"FILE");
646    gfile->value=zStrdup(tmp->value);
647    sagaExecuteCmd(conf,"io_gdal","1",arg);
648  }
649  else{
650    // Empty result
651    return true;
652  }
653  freeMap(&arg);
654  free(arg);
655}
656
657/**
658 * Export a SAGA-GIS TIN to a file in a specific format (GML,KML,GeoJSON).
659 * Exporting TIN produce 5 separated files (POINTS, CENTER, EDGES, TRIANGLES
660 * and POLYGONS). Even if a client can choose which result it want to have,
661 * SAGA-GIS module will be invoked in a way that it will produce in any case
662 * each possible outputs. The selection of a specific output is made in the
663 * ZOO-Kernel itself and not specifically at this level.
664 * saga_cmd tin_tools 3 -TIN my.shp -POINTS p.shp ...
665 *
666 * @param conf the conf maps containing the main.cfg settings
667 * @param in the output maps to fill with the resulting file
668 * @see sagaExportOGR
669 */
670int sagaExportTIN(maps** conf, maps** in,const char* tname/*,CSG_Parameter* param*/){
671  dumpMaps(*in);
672  map* mtype=getMap((*in)->content,"mimeType");
673  map* gfile=getMap((*in)->content,"generated_file");
674  char* fext="shp";
675  map* arg=createMap("TIN",gfile->value);
676
677  char* tinOut[5]={
678    "POINTS",
679    "CENTER",
680    "EDGES",
681    "TRIANGLES",
682    "POLYGONS"
683  };
684  maps* resouts=NULL;
685
686  int i=0;
687  for(i=0;i<5;i++){
688    char* tmpName=(char*)malloc((strlen(gfile->value)+strlen(tinOut[i])+4)*sizeof(char));
689    strncpy(tmpName,gfile->value,(strlen(gfile->value)-3)*sizeof(char));
690    char *tmpSubName=(char*) malloc((strlen(tinOut[i])+3)*sizeof(char));
691    sprintf(tmpSubName,"_%s.",tinOut[i]);
692    strncpy(&tmpName[0]+(strlen(gfile->value)-4),tmpSubName,(strlen(tmpSubName))*sizeof(char));
693    strncpy(&tmpName[0]+(strlen(gfile->value)+strlen(tmpSubName)-4),fext,(strlen(fext))*sizeof(char));
694    tmpName[strlen(fext)+(strlen(gfile->value)+strlen(tmpSubName)-4)]=0;
695
696    maps* louts=(maps*)malloc(MAPS_SIZE);
697    louts->name=zStrdup(tinOut[i]);
698    louts->content=createMap("mimeType","UNKOWN");
699    louts->next=NULL;
700   
701    addToMap(arg,tinOut[i],tmpName);
702   
703    free(tmpName);
704    if(resouts==NULL)
705      resouts=dupMaps(&louts);
706    else
707      addMapsToMaps(&resouts,louts);
708    freeMaps(&louts);
709    free(louts);
710  }
711 
712  sagaExecuteCmd(conf,"tin_tools","3",arg,&resouts);
713
714  for(i=0;i<5;i++){
715    map* generatedFile=getMapFromMaps(resouts,tinOut[i],"generated_file");
716    setMapInMaps(*in,(CSG_String(tname)+"_"+tinOut[i]).b_str(),"generated_file",generatedFile->value);
717    maps* cout=getMaps(*in,(CSG_String(tname)+"_"+tinOut[i]).b_str());
718    sagaExportOGR(conf,&cout);
719  }
720  return true;
721}
722
723/**
724 * Import GDAL Datasource into SAGA-GIS.
725 * saga_cmd io_gdal 0 -TRANSFORM 0 -FILES my.format -GRIDS /tmpPath/MyGridXXX.sgrd
726 *
727 * @param conf the conf maps containing the main.cfg settings
728 * @param in in the inputs maps
729 */
730int sagaImportGDAL(maps** conf, maps** in){
731  map* l=getMap((*in)->content,"length");
732  bool shouldClean=false;
733  if(l==NULL){
734    l=createMap("length","1");
735    shouldClean=true;
736  }
737  int len=strtol(l->value,NULL,10);
738  int i=0;
739  for(i=0;i<len;i++){
740    map* arg=createMap("TRANSFORM","0");
741    addToMap(arg,"INTERPOL","4");
742    map* v=getMapArray((*in)->content,"cache_file",i);
743    if(v!=NULL)
744      addToMap(arg,"FILES",v->value);
745    addToMap(arg,"GRIDS","");
746
747    maps* louts=(maps*)malloc(MAPS_SIZE);
748    louts->name=zStrdup("GRIDS");
749    louts->content=createMap("mimeType","UNKOWN");
750    louts->next=NULL;
751
752    sagaExecuteCmd(conf,"io_gdal","0",arg,&louts);
753
754    map* tmp=getMapFromMaps(louts,"GRIDS","generated_file");
755    setMapArray((*in)->content,"saga_value",i,tmp->value);
756
757    freeMaps(&louts);
758    free(louts);
759    freeMap(&arg);
760    free(arg);
761  }
762  if(shouldClean){
763    freeMap(&l);
764    free(l);
765  }
766}
767
768/**
769 * Import OGR Datasource into SAGA-GIS.
770 * saga_cmd io_gdal 3 -SHAPES my.shp -FILES my.format
771 *
772 * @param conf the conf maps containing the main.cfg settings
773 * @param in in the inputs maps
774 */
775int sagaImportOGR(maps** conf, maps** in){
776  char *ext;
777  map* arg;
778  map* l=getMap((*in)->content,"length");
779  bool shouldClean=false;
780  if(l==NULL){
781    l=createMap("length","1");
782    shouldClean=true;
783  }
784  int len=strtol(l->value,NULL,10);
785  int i=0;
786  for(i=0;i<len;i++){
787    map* v=getMapArray((*in)->content,"cache_file",i);
788    arg=createMap("SHAPES","");
789    if(v!=NULL)
790      addToMap(arg,"FILES",v->value);
791
792    maps* louts=(maps*)malloc(MAPS_SIZE);
793    louts->name=zStrdup("SHAPES");
794    louts->content=createMap("mimeType","UNKOWN");
795    louts->next=NULL;
796
797    sagaExecuteCmd(conf,"io_gdal","3",arg,&louts);
798
799    map* tmp=getMapFromMaps(louts,"SHAPES","generated_file");
800    setMapArray((*in)->content,"saga_value",i,tmp->value);
801
802    freeMaps(&louts);
803    free(louts);
804    freeMap(&arg);
805    free(arg);
806  }
807  if(shouldClean){
808    freeMap(&l);
809    free(l);
810  }
811}
812
813/**
814 * Import TIN into SAGA-GIS. Calling this function suppose that sagaImportOGR
815 * was called first.
816 * saga_cmd tin_tools 2 -SHAPES myShapes.shp -TIN myTin.shp
817 *
818 * @param conf the conf maps containing the main.cfg settings
819 * @param in in the inputs maps
820 * @see sagaImportOGR
821 */
822bool sagaImportTIN(maps** conf, maps** in){
823  char *ext;
824  map* arg;
825  map* l=getMap((*in)->content,"length");
826  bool shouldClean=false;
827  if(l==NULL){
828    l=createMap("length","1");
829    shouldClean=true;
830  }
831  int len=strtol(l->value,NULL,10);
832  int i=0;
833  for(i=0;i<len;i++){
834    map* v=getMapArray((*in)->content,"saga_value",i);
835    arg=createMap("TIN","");
836    if(v!=NULL)
837      addToMap(arg,"SHAPES",v->value);
838    maps* louts=(maps*)malloc(MAPS_SIZE);
839    louts->name=zStrdup("TIN");
840    louts->content=createMap("mimeType","UNKOWN");
841    louts->next=NULL;
842    sagaExecuteCmd(conf,"tin_tools","2",arg,&louts);
843    map* tmp=getMapFromMaps(louts,"TIN","generated_file");
844    v=getMapArray((*in)->content,"saga_value",i);
845    if(tmp!=NULL){
846      if(v!=NULL){
847        free(v->value);
848        v->value=zStrdup(tmp->value);
849      }
850      else
851        setMapArray((*in)->content,"saga_value",i,tmp->value);
852    }
853    freeMaps(&louts);
854    free(louts);
855    freeMap(&arg);
856    free(arg);
857  }
858  if(shouldClean){
859    freeMap(&l);
860    free(l);
861  }
862  return true;
863}
864
865/**
866 * Import table into SAGA-GIS.
867 * saga_cmd io_table 1 -TABLE myTable -FILENAME myFile -SEPARATOR 2
868 *
869 * @param conf the conf maps containing the main.cfg settings
870 * @param in in the inputs maps
871 */
872int sagaImportTable(maps** conf, maps** in){
873  char *ext;
874  map* arg;
875  map* l=getMap((*in)->content,"length");
876  bool shouldClean=false;
877  if(l==NULL){
878    l=createMap("length","1");
879    shouldClean=true;
880  }
881  int len=strtol(l->value,NULL,10);
882  int i=0;
883  for(i=0;i<len;i++){
884
885    // Create and fill arg map
886    arg=createMap("SEPARATOR","2");
887    addToMap(arg,"TABLE","");
888    map* v=getMapArray((*in)->content,"cache_file",i);
889    if(v!=NULL)
890      addToMap(arg,"FILENAME",v->value);
891
892    // Create the output maps
893    maps* louts=(maps*)malloc(MAPS_SIZE);
894    louts->name=zStrdup("TABLE");
895    louts->content=createMap("mimeType","UNKOWN");
896    louts->next=NULL;
897
898    // Execute the saga command
899    sagaExecuteCmd(conf,"io_table","1",arg,&louts);
900
901    // Fetch result and add it to the original map as saga_value
902    map* tmp=getMapFromMaps(louts,"TABLE","generated_file");
903    setMapArray((*in)->content,"saga_value",i,tmp->value);
904
905    // Cleanup
906    freeMaps(&louts);
907    free(louts);
908    freeMap(&arg);
909    free(arg);
910
911  }
912  // Cleanup if required
913  if(shouldClean){
914    freeMap(&l);
915    free(l);
916  }
917}
918
919/**
920 * Import las file as pointcloud into SAGA-GIS.
921 * saga_cmd io_shapes_las 1 -POINTS my.spc -FILENAME my.las
922 *
923 * @param conf the conf maps containing the main.cfg settings
924 * @param in in the inputs maps
925 */
926int sagaImportPC(maps** conf, maps** in){
927  char *ext;
928  map* arg;
929  map* l=getMap((*in)->content,"length");
930  bool shouldClean=false;
931  if(l==NULL){
932    l=createMap("length","1");
933    shouldClean=true;
934  }
935  int len=strtol(l->value,NULL,10);
936  int i=0;
937  for(i=0;i<len;i++){
938
939    // Create and fill arg map
940    arg=createMap("POINTS","");
941    map* v=getMapArray((*in)->content,"cache_file",i);
942    if(v!=NULL)
943      addToMap(arg,"FILES",v->value);
944
945    // Create the output maps
946    maps* louts=(maps*)malloc(MAPS_SIZE);
947    louts->name=zStrdup("POINTS");
948    louts->content=createMap("mimeType","UNKOWN");
949    louts->next=NULL;
950
951    // Execute the saga command
952    sagaExecuteCmd(conf,"io_shapes_las","1",arg,&louts);
953
954    // Fetch result and add it to the original map as saga_value
955    map* tmp=getMapFromMaps(louts,"POINTS","generated_file");
956    setMapArray((*in)->content,"saga_value",i,tmp->value);
957
958    // Cleanup
959    freeMaps(&louts);
960    free(louts);
961    freeMap(&arg);
962    free(arg);
963
964  }
965  // Cleanup if required
966  if(shouldClean){
967    freeMap(&l);
968    free(l);
969  }
970}
971
972/**
973 * Load and invoke a SAGA-GIS module defined in a service metadata definitions.
974 * Load all the input data into SAGA-GIS using io_gdal, io_tables and
975 * io_shapes_las for SAGA grids/shapes, tables and pointcloud respectively.
976 * Load and run the module from its library and invoke it using the data
977 * imported in SAGA-GIS at first stage. After the execution, export the outputs
978 * to files using io_gdal and io_shapes_las for grids/shapes and pointcloud
979 * respectively.
980 *
981 * @param main_conf the conf maps containing the main.cfg settings
982 * @param request the map containing the HTTP request
983 * @param s the service structure
984 * @param inputs the maps containing the inputs
985 * @param outputs the maps containing the outputs
986 */
987int zoo_saga_support(maps** main_conf,map* request,service* s,maps** inputs,maps** outputs){
988  int res=SERVICE_FAILED;
989  if( !wxInitialize() ){
990    fprintf(stderr,"initialisation failed");
991    return SERVICE_FAILED;
992  }
993  setlocale(LC_NUMERIC, "C");
994  static bool g_bShow_Messages = false;
995
996  dumpMapsValuesToFiles(main_conf,inputs);
997
998  SagaWatcher watcher=SagaWatcher();
999  watcher.SetConf(main_conf);
1000
1001  SG_Set_UI_Callback(Get_Callback(watcher));
1002
1003  int n = SG_Get_Module_Library_Manager().Add_Directory(wxT(MODULE_LIBRARY_PATH),false);
1004  if( SG_Get_Module_Library_Manager().Get_Count() <= 0 ){
1005    setMapInMaps(*main_conf,"lenv","message","Could not load any SAGA tool library");
1006    res=SERVICE_FAILED;
1007    return res;
1008  }
1009
1010  map* serviceProvider=getMap(s->content,"serviceProvider");
1011
1012  // Load the SAGA-GIS library corresponding to the serviceProvider
1013  CSG_Module_Library * library=SG_Get_Module_Library_Manager().Get_Library(CSG_String(serviceProvider->value),true);
1014  if( library == NULL){
1015    char tmp[255];
1016    sprintf(tmp,"Counld not load the %s SAGA library",serviceProvider->value);
1017    setMapInMaps(*main_conf,"lenv","message",tmp);
1018    res=SERVICE_FAILED;
1019    return res;
1020  }
1021 
1022  // Load the SAGA-GIS module corresponding to the service name from the library
1023  CSG_Module * module=library->Get_Module(atoi(s->name));
1024  if(module == NULL){
1025    char tmp[255];
1026    sprintf(tmp,"Counld not load the %s module from the %s SAGA library",
1027            s->name,serviceProvider->value);
1028    setMapInMaps(*main_conf,"lenv","message",tmp);
1029    res=SERVICE_FAILED;
1030    return res;
1031  }
1032
1033  // Load all the parameters defined for the module
1034  CSG_Parameters * params=module->Get_Parameters();
1035  int pc=params->Get_Count();
1036  if(!params){
1037    char tmp[255];
1038    sprintf(tmp,"Counld not find any param for the %s module from the %s SAGA library",
1039            s->name,serviceProvider->value);
1040    setMapInMaps(*main_conf,"lenv","message",tmp);
1041    res=SERVICE_FAILED;
1042    return res;
1043  }
1044
1045  // Loop over each inputs to transform raster files to grid when needed,
1046  // import tables, shapes or point clouds
1047  for(int k=0;k<pc;k++){
1048    CSG_Parameter * param=params->Get_Parameter(k);
1049    if(param!=NULL && !param->is_Output()){
1050      maps* inmap=getMaps(*inputs,CSG_String(param->Get_Identifier()).b_str());
1051      if(inmap!=NULL){
1052        map* tmp=getMap(inmap->content,"value");
1053        if(tmp==NULL || strncasecmp(tmp->value,"NULL",4)!=0){
1054          if(CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("grid"))){
1055            sagaImportGDAL(main_conf,&inmap);
1056          }
1057          else if(CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("tin"))){
1058            sagaImportOGR(main_conf,&inmap);
1059            sagaImportTIN(main_conf,&inmap);
1060          }
1061          else if(CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("shapes"))){
1062            sagaImportOGR(main_conf,&inmap);
1063          }
1064          else{
1065            if(CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("table"))){
1066              sagaImportTable(main_conf,&inmap);
1067            }
1068            else
1069              if(CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("points"))){
1070                sagaImportPC(main_conf,&inmap);
1071              }
1072          }
1073        }
1074      }
1075    }
1076  }
1077
1078  // Create a map conraining arguments to pass to the SAGA-GIS module
1079  // Fetch all input value (specifically for data imported into SAGA-GIS)
1080  maps* inp=*inputs;
1081  int k=0;
1082  map* cParams=NULL;
1083  while(inp!=NULL){
1084    map* len=getMap(inp->content,"length");
1085    bool shouldClean=false;
1086    if(len==NULL){
1087      len=createMap("length","1");
1088      shouldClean=true;
1089    }
1090    int len0=strtol(len->value,NULL,10);
1091    int i=0;
1092    char *cinput=NULL;
1093    int clen=0;
1094    for(i=0;i<len0;i++){
1095      map* val=getMapArray(inp->content,"saga_value",i);
1096      if(val==NULL)
1097        val=getMapArray(inp->content,"value",i);
1098      if(val!=NULL && strncasecmp(val->value,"NULL",4)!=0){
1099        if(cinput==NULL){
1100          cinput=zStrdup(val->value);
1101        }
1102        else{
1103          cinput=(char*)realloc(cinput,(clen+strlen(val->value)+1)*sizeof(char));
1104          strncpy(&cinput[0]+clen,";",1);
1105          strncpy(&cinput[0]+(clen+1),val->value,strlen(val->value));
1106          clen+=1;
1107        }
1108        clen+=strlen(val->value);
1109        cinput[clen]=0;
1110      }
1111    }
1112    if(cinput!=NULL && strncasecmp(cinput,"NULL",4)!=0){
1113      if(cParams==NULL)
1114        cParams=createMap(inp->name,cinput);
1115      else
1116        addToMap(cParams,inp->name,cinput);
1117      free(cinput);
1118    }
1119    inp=inp->next;
1120  }
1121
1122  // Fetch all output and define a resulting filename
1123  inp=*outputs;
1124  map* tmpPath=getMapFromMaps(*main_conf,"main","tmpPath");
1125  map* sid=getMapFromMaps(*main_conf,"lenv","usid");
1126  while(inp!=NULL){
1127    for(int k=0;k<pc;k++){
1128      CSG_Parameter * param=params->Get_Parameter(k);
1129      if(CSG_String(param->Get_Identifier()).Cmp(inp->name)==0){
1130        const char *file_ext=sagaGetDefaultExt(param);
1131        char *fileName=(char*)malloc((strlen(file_ext)+strlen(sid->value)+strlen(inp->name)+strlen(tmpPath->value)+11)*sizeof(char));
1132        sprintf(fileName,"%s/Output_%s_%s.%s",tmpPath->value,inp->name,sid->value,file_ext);
1133        if(cParams==NULL)
1134          cParams=createMap(inp->name,fileName);
1135        else
1136          addToMap(cParams,inp->name,fileName);
1137      }
1138    }
1139    inp=inp->next;
1140  }
1141
1142  sagaSetParameters(params,cParams);
1143
1144  module->Update_Parameter_States();
1145 
1146  bool retval=false;
1147  if(module->On_Before_Execution()){
1148    retval=module->Execute();
1149    module->On_After_Execution();
1150  }
1151
1152  sagaSaveOutputs(params,*main_conf,outputs);
1153
1154  // Loop over each outputs to transform grid to raster file when needed,
1155  // export tables, shapes or point clouds
1156  for(int k=0;k<pc;k++){
1157    CSG_Parameter * param=params->Get_Parameter(k);
1158    if(param!=NULL && param->is_Output()){
1159      maps* inmap=getMaps(*outputs,CSG_String(param->Get_Identifier()).b_str());
1160      if(inmap!=NULL){
1161        if(CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("grid"))
1162           || CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("data_object"))){
1163          sagaExportGDAL(main_conf,&inmap);
1164        }else{
1165          if(CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("shapes"))){
1166            sagaExportOGR(main_conf,&inmap);
1167          }
1168          else{
1169            if(CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("table"))){
1170            }
1171            else{
1172              if(CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("tin"))){
1173                sagaExportTIN(main_conf,&inmap,"TIN");
1174              }
1175              else
1176                if(CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("points"))){
1177                  sagaExportPC(main_conf,&inmap);
1178              }
1179            }
1180          }
1181        }
1182      }
1183      else if(CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("tin"))){
1184        sagaExportTIN(main_conf,outputs,CSG_String(param->Get_Identifier()).b_str());
1185      }
1186             
1187    }
1188  }
1189
1190  wxUninitialize();
1191
1192  return SERVICE_SUCCEEDED;
1193}
Note: See TracBrowser for help on using the repository browser.

Search

Context Navigation

ZOO Sponsors

http://www.zoo-project.org/trac/chrome/site/img/geolabs-logo.pnghttp://www.zoo-project.org/trac/chrome/site/img/neogeo-logo.png http://www.zoo-project.org/trac/chrome/site/img/apptech-logo.png http://www.zoo-project.org/trac/chrome/site/img/3liz-logo.png http://www.zoo-project.org/trac/chrome/site/img/gateway-logo.png

Become a sponsor !

Knowledge partners

http://www.zoo-project.org/trac/chrome/site/img/ocu-logo.png http://www.zoo-project.org/trac/chrome/site/img/gucas-logo.png http://www.zoo-project.org/trac/chrome/site/img/polimi-logo.png http://www.zoo-project.org/trac/chrome/site/img/fem-logo.png http://www.zoo-project.org/trac/chrome/site/img/supsi-logo.png http://www.zoo-project.org/trac/chrome/site/img/cumtb-logo.png

Become a knowledge partner

Related links

http://zoo-project.org/img/ogclogo.png http://zoo-project.org/img/osgeologo.png