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

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

Fix issue reported by Alex in the Saga support.

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

Search

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