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

Last change on this file since 639 was 639, checked in by djay, 10 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