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

Last change on this file since 640 was 640, checked in by djay, 7 years ago

First version including zoo_service shared library

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