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

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

Small fix for fixing issue in GetStatus? due to file name similar to the temporary stored ExecuteResponse?.

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