source: trunk/zoo-services/ogr/ogr2ogr/service.c @ 102

Last change on this file since 102 was 49, checked in by nmarco, 14 years ago

I Correct the path to the output data: now refers to the url path (tmpUrl) of the web service, instead to the server path (tmpPath)

File size: 41.9 KB
Line 
1/******************************************************************************
2 * $Id: ogr2ogr.cpp 15473 2008-10-07 20:59:24Z warmerdam $
3 *
4 * Project:  OpenGIS Simple Features Reference Implementation
5 * Purpose:  Simple client for translating between formats.
6 * Author:   Frank Warmerdam, warmerdam@pobox.com
7 *
8 ******************************************************************************
9 * Copyright (c) 1999, Frank Warmerdam
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a
12 * copy of this software and associated documentation files (the "Software"),
13 * to deal in the Software without restriction, including without limitation
14 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 * and/or sell copies of the Software, and to permit persons to whom the
16 * Software is furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included
19 * in all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 * DEALINGS IN THE SOFTWARE.
28 ****************************************************************************/
29
30#include "ogrsf_frmts.h"
31#include "ogr_p.h"
32#include "cpl_conv.h"
33#include "cpl_string.h"
34#include "ogr_api.h"
35#ifdef ZOO_SERVICE
36#include "service.h"
37#endif
38
39CPL_CVSID("$Id: ogr2ogr.cpp 15473 2008-10-07 20:59:24Z warmerdam $");
40
41#ifdef ZOO_SERVICE
42extern "C" {
43#endif
44
45static void Usage();
46
47static int TranslateLayer( OGRDataSource *poSrcDS, 
48                           OGRLayer * poSrcLayer,
49                           OGRDataSource *poDstDS,
50                           char ** papszLSCO,
51                           const char *pszNewLayerName,
52                           int bTransform, 
53                           OGRSpatialReference *poOutputSRS,
54                           OGRSpatialReference *poSourceSRS,
55                           char **papszSelFields,
56                           int bAppend, int eGType,
57                           int bOverwrite,
58                           double dfMaxSegmentLength);
59
60static int bSkipFailures = FALSE;
61static int nGroupTransactions = 200;
62static int bPreserveFID = FALSE;
63static int nFIDToFetch = OGRNullFID;
64
65/************************************************************************/
66/*                                main()                                */
67/************************************************************************/
68
69#ifdef ZOO_SERVICE
70#ifdef WIN32
71__declspec(dllexport)
72#endif
73int Ogr2Ogr(maps*& conf,maps*& inputs,maps*& outputs)
74#else
75int main( int nArgc, char ** papszArgv )
76#endif
77{
78    const char  *pszFormat = "ESRI Shapefile";
79    const char  *pszDataSource = NULL;
80    const char  *pszDestDataSource = NULL;
81    const char  *pszwebDestData = NULL;
82    char        **papszLayers = NULL;
83    char        **papszDSCO = NULL, **papszLCO = NULL;
84    int         bTransform = FALSE;
85    int         bAppend = FALSE, bUpdate = FALSE, bOverwrite = FALSE;
86    const char  *pszOutputSRSDef = NULL;
87    const char  *pszSourceSRSDef = NULL;
88    OGRSpatialReference *poOutputSRS = NULL;
89    OGRSpatialReference *poSourceSRS = NULL;
90    const char  *pszNewLayerName = NULL;
91    const char  *pszWHERE = NULL;
92    OGRGeometry *poSpatialFilter = NULL;
93    const char  *pszSelect;
94    char        **papszSelFields = NULL;
95    const char  *pszSQLStatement = NULL;
96    int         eGType = -2;
97    double       dfMaxSegmentLength = 0;
98
99    /* Check strict compilation and runtime library version as we use C++ API */
100    if (! GDAL_CHECK_VERSION("ogr2ogr"))
101#ifdef ZOO_SERVICE
102        {
103                fprintf(stderr,"Not correct version of the gdal library\n");
104                setMapInMaps(conf,"lenv","message","Unable to check gdal version for ogr2ogr_service.zo");
105                return SERVICE_FAILED;
106        }
107#else
108        exit(1);
109#endif
110/* -------------------------------------------------------------------- */
111/*      Register format(s).                                             */
112/* -------------------------------------------------------------------- */
113    OGRRegisterAll();
114
115#ifdef ZOO_SERVICE
116    map *tmpMap=NULL;
117    char dataPath[1024];
118    tmpMap=getMapFromMaps(conf,"main","dataPath");
119    if(tmpMap!=NULL)
120      sprintf(dataPath,"%s",tmpMap->value);
121    tmpMap=NULL;
122    char tempPath[1024];
123    tmpMap=getMapFromMaps(conf,"main","tmpPath");
124    if(tmpMap!=NULL){
125      sprintf(tempPath,"%s",tmpMap->value);
126    }
127   
128    tmpMap=NULL;
129    char serverAddress[1024];
130    tmpMap=getMapFromMaps(conf,"main","serverAddress");
131    if(tmpMap!=NULL){
132      sprintf(serverAddress,"%s",tmpMap->value);
133    }
134   
135    tmpMap=NULL;
136    char tmpurl[1024];
137    tmpMap=getMapFromMaps(conf,"main","tmpurl");
138    if(tmpMap!=NULL){
139      sprintf(tmpurl,"%s",tmpMap->value);
140    }
141
142    tmpMap=NULL;
143    tmpMap=getMapFromMaps(inputs,"F","value");
144    if(tmpMap!=NULL){
145      pszFormat=tmpMap->value;
146    }
147
148    tmpMap=NULL;
149    tmpMap=getMapFromMaps(inputs,"DSCO","value");
150    if(tmpMap!=NULL){
151          papszDSCO = CSLAddString(papszDSCO, tmpMap->value );
152    }
153
154    tmpMap=NULL;
155    tmpMap=getMapFromMaps(inputs,"LCO","value");
156    if(tmpMap!=NULL){
157          papszLCO = CSLAddString(papszLCO, tmpMap->value );
158    }
159
160    tmpMap=NULL;
161    tmpMap=getMapFromMaps(inputs,"preserve_fid","value");
162    if(tmpMap!=NULL){
163          bPreserveFID = TRUE;
164    }
165
166    tmpMap=NULL;
167    tmpMap=getMapFromMaps(inputs,"skipfailure","value");
168    if(tmpMap!=NULL){
169          bPreserveFID = TRUE;
170          bSkipFailures = TRUE;
171          nGroupTransactions = 1; /* #2409 */
172    }
173
174    tmpMap=NULL;
175    tmpMap=getMapFromMaps(inputs,"append","value");
176    if(tmpMap!=NULL){
177          bAppend = TRUE;
178    }
179
180    tmpMap=NULL;
181    tmpMap=getMapFromMaps(inputs,"overwrite","value");
182    if(tmpMap!=NULL){
183          bOverwrite = TRUE;
184    }
185
186    tmpMap=NULL;
187    tmpMap=getMapFromMaps(inputs,"update","value");
188    if(tmpMap!=NULL){
189          bUpdate = TRUE;
190    }
191
192    tmpMap=NULL;
193    tmpMap=getMapFromMaps(inputs,"fid","value");
194    if(tmpMap!=NULL){
195          nFIDToFetch = atoi(tmpMap->value);
196    }
197
198    tmpMap=NULL;
199    tmpMap=getMapFromMaps(inputs,"sql","value");
200    if(tmpMap!=NULL){
201          pszSQLStatement = tmpMap->value;
202    }
203
204    tmpMap=NULL;
205    tmpMap=getMapFromMaps(inputs,"nln","value");
206    if(tmpMap!=NULL){
207          pszNewLayerName = tmpMap->value;
208    }
209
210    tmpMap=NULL;
211    tmpMap=getMapFromMaps(inputs,"nlt","value");
212    if(tmpMap!=NULL){
213          pszNewLayerName = tmpMap->value;
214          if( EQUAL(tmpMap->value,"NONE") )
215                  eGType = wkbNone;
216          else if( EQUAL(tmpMap->value,"GEOMETRY") )
217                  eGType = wkbUnknown;
218          else if( EQUAL(tmpMap->value,"POINT") )
219                  eGType = wkbPoint;
220          else if( EQUAL(tmpMap->value,"LINESTRING") )
221                  eGType = wkbLineString;
222          else if( EQUAL(tmpMap->value,"POLYGON") )
223                  eGType = wkbPolygon;
224          else if( EQUAL(tmpMap->value,"GEOMETRYCOLLECTION") )
225                  eGType = wkbGeometryCollection;
226          else if( EQUAL(tmpMap->value,"MULTIPOINT") )
227                  eGType = wkbMultiPoint;
228          else if( EQUAL(tmpMap->value,"MULTILINESTRING") )
229                  eGType = wkbMultiLineString;
230          else if( EQUAL(tmpMap->value,"MULTIPOLYGON") )
231                  eGType = wkbMultiPolygon;
232          else if( EQUAL(tmpMap->value,"GEOMETRY25D") )
233                  eGType = wkbUnknown | wkb25DBit;
234          else if( EQUAL(tmpMap->value,"POINT25D") )
235                  eGType = wkbPoint25D;
236          else if( EQUAL(tmpMap->value,"LINESTRING25D") )
237                  eGType = wkbLineString25D;
238          else if( EQUAL(tmpMap->value,"POLYGON25D") )
239                  eGType = wkbPolygon25D;
240          else if( EQUAL(tmpMap->value,"GEOMETRYCOLLECTION25D") )
241                  eGType = wkbGeometryCollection25D;
242          else if( EQUAL(tmpMap->value,"MULTIPOINT25D") )
243                  eGType = wkbMultiPoint25D;
244          else if( EQUAL(tmpMap->value,"MULTILINESTRING25D") )
245                  eGType = wkbMultiLineString25D;
246          else if( EQUAL(tmpMap->value,"MULTIPOLYGON25D") )
247                  eGType = wkbMultiPolygon25D;
248          else   
249          {
250                  fprintf( stderr, "-nlt %s: type not recognised.\n", 
251                          tmpMap->value );
252                  exit( 1 );
253          }
254    }
255
256    tmpMap=NULL;
257    tmpMap=getMapFromMaps(inputs,"tg","value");
258    if(tmpMap!=NULL){
259          nGroupTransactions = atoi(tmpMap->value);
260    }
261
262    tmpMap=NULL;
263    tmpMap=getMapFromMaps(inputs,"s_srs","value");
264    if(tmpMap!=NULL){
265          pszSourceSRSDef = tmpMap->value;
266    }
267
268    tmpMap=NULL;
269    tmpMap=getMapFromMaps(inputs,"a_srs","value");
270    if(tmpMap!=NULL){
271          pszOutputSRSDef = tmpMap->value;
272    }
273
274    tmpMap=NULL;
275    tmpMap=getMapFromMaps(inputs,"t_srs","value");
276    if(tmpMap!=NULL){
277          pszOutputSRSDef = tmpMap->value;
278          bTransform = TRUE;
279    }
280
281    tmpMap=NULL;
282    tmpMap=getMapFromMaps(inputs,"SPAT","value");
283    if(tmpMap!=NULL){
284      char *tmp=tmpMap->value;
285      char *t=strtok(tmp,",");
286      int cnt=0;
287      double dfULX, dfULY, dfLRX, dfLRY;
288      while(t!=NULL){
289        switch(cnt){
290        case 0:
291          dfULX = atof(t);
292          break;
293        case 1:
294          dfULY = atof(t);
295          break;
296        case 2:
297          dfLRX = atof(t);
298          break;
299        case 3:
300          dfLRY = atof(t);
301          break;
302        }
303        fprintf(stderr,"%s\n\n",t);
304        fprintf(stderr,"%f - %f - %f - %f\n\n",dfULX,dfULY,dfLRX,dfLRY);
305        t=strtok(NULL,",");
306        cnt++;
307      }
308
309      OGRLinearRing  oRing;
310     
311      oRing.addPoint( dfULX, dfULY );
312      oRing.addPoint( dfULX, dfLRY );
313      oRing.addPoint( dfLRX, dfLRY );
314      oRing.addPoint( dfLRX, dfULY );
315      oRing.addPoint( dfULX, dfULY );
316      poSpatialFilter = new OGRPolygon();
317      ((OGRPolygon *) poSpatialFilter)->addRing( &oRing );
318    }
319
320    tmpMap=NULL;
321    tmpMap=getMapFromMaps(inputs,"where","value");
322    if(tmpMap!=NULL){
323          pszWHERE = tmpMap->value;
324    }
325
326    tmpMap=NULL;
327    tmpMap=getMapFromMaps(inputs,"select","value");
328    if(tmpMap!=NULL){
329          pszSelect = tmpMap->value;
330          papszSelFields = CSLTokenizeStringComplex(pszSelect, " ,", 
331                  FALSE, FALSE );
332    }
333
334    tmpMap=NULL;
335    tmpMap=getMapFromMaps(inputs,"segmentize","value");
336    if(tmpMap!=NULL){
337          dfMaxSegmentLength = atof(tmpMap->value);
338    }
339
340    tmpMap=NULL;
341    tmpMap=getMapFromMaps(inputs,"segmentize","value");
342    if(tmpMap!=NULL){
343          dfMaxSegmentLength = atof(tmpMap->value);
344    }
345
346    tmpMap=NULL;
347    tmpMap=getMapFromMaps(inputs,"InputDSN","value");
348    if(tmpMap!=NULL){
349      pszDataSource=(char*)malloc(sizeof(char)*(strlen(dataPath)+strlen(tmpMap->value)+1));
350      sprintf((char*)pszDataSource,"%s/%s",dataPath,tmpMap->value);
351    }
352
353    tmpMap=NULL;
354    tmpMap=getMapFromMaps(inputs,"OutputDSN","value");
355    if(tmpMap!=NULL){
356      pszDestDataSource=(char*)malloc(sizeof(char)*(strlen(tempPath)+strlen(tmpMap->value)+4));
357      sprintf((char*)pszDestDataSource,"%s/%s",tempPath,tmpMap->value/*,ext*/);
358      pszwebDestData=(char*)malloc(sizeof(char)*(strlen(serverAddress)+strlen(tmpurl)+strlen(tmpMap->value)+4));
359      sprintf((char*)pszwebDestData,"%s%s/%s",serverAddress,tmpurl,tmpMap->value/*,ext*/);
360    }
361
362#else
363/* -------------------------------------------------------------------- */
364/*      Processing command line arguments.                              */
365/* -------------------------------------------------------------------- */
366    nArgc = OGRGeneralCmdLineProcessor( nArgc, &papszArgv, 0 );
367   
368    if( nArgc < 1 )
369        exit( -nArgc );
370
371    for( int iArg = 1; iArg < nArgc; iArg++ )
372    {
373        if( EQUAL(papszArgv[iArg], "--utility_version") )
374        {
375                                printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
376                   papszArgv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
377            return 0;
378        }
379        else if( EQUAL(papszArgv[iArg],"-f") && iArg < nArgc-1 )
380        {
381            pszFormat = papszArgv[++iArg];
382        }
383        else if( EQUAL(papszArgv[iArg],"-dsco") && iArg < nArgc-1 )
384        {
385            papszDSCO = CSLAddString(papszDSCO, papszArgv[++iArg] );
386        }
387        else if( EQUAL(papszArgv[iArg],"-lco") && iArg < nArgc-1 )
388        {
389            papszLCO = CSLAddString(papszLCO, papszArgv[++iArg] );
390        }
391        else if( EQUAL(papszArgv[iArg],"-preserve_fid") )
392        {
393            bPreserveFID = TRUE;
394        }
395        else if( EQUALN(papszArgv[iArg],"-skip",5) )
396        {
397            bSkipFailures = TRUE;
398            nGroupTransactions = 1; /* #2409 */
399        }
400        else if( EQUAL(papszArgv[iArg],"-append") )
401        {
402            bAppend = TRUE;
403        }
404        else if( EQUAL(papszArgv[iArg],"-overwrite") )
405        {
406            bOverwrite = TRUE;
407        }
408        else if( EQUAL(papszArgv[iArg],"-update") )
409        {
410            bUpdate = TRUE;
411        }
412        else if( EQUAL(papszArgv[iArg],"-fid") && papszArgv[iArg+1] != NULL )
413        {
414            nFIDToFetch = atoi(papszArgv[++iArg]);
415        }
416        else if( EQUAL(papszArgv[iArg],"-sql") && papszArgv[iArg+1] != NULL )
417        {
418            pszSQLStatement = papszArgv[++iArg];
419        }
420        else if( EQUAL(papszArgv[iArg],"-nln") && iArg < nArgc-1 )
421        {
422            pszNewLayerName = papszArgv[++iArg];
423        }
424        else if( EQUAL(papszArgv[iArg],"-nlt") && iArg < nArgc-1 )
425        {
426            if( EQUAL(papszArgv[iArg+1],"NONE") )
427                eGType = wkbNone;
428            else if( EQUAL(papszArgv[iArg+1],"GEOMETRY") )
429                eGType = wkbUnknown;
430            else if( EQUAL(papszArgv[iArg+1],"POINT") )
431                eGType = wkbPoint;
432            else if( EQUAL(papszArgv[iArg+1],"LINESTRING") )
433                eGType = wkbLineString;
434            else if( EQUAL(papszArgv[iArg+1],"POLYGON") )
435                eGType = wkbPolygon;
436            else if( EQUAL(papszArgv[iArg+1],"GEOMETRYCOLLECTION") )
437                eGType = wkbGeometryCollection;
438            else if( EQUAL(papszArgv[iArg+1],"MULTIPOINT") )
439                eGType = wkbMultiPoint;
440            else if( EQUAL(papszArgv[iArg+1],"MULTILINESTRING") )
441                eGType = wkbMultiLineString;
442            else if( EQUAL(papszArgv[iArg+1],"MULTIPOLYGON") )
443                eGType = wkbMultiPolygon;
444            else if( EQUAL(papszArgv[iArg+1],"GEOMETRY25D") )
445                eGType = wkbUnknown | wkb25DBit;
446            else if( EQUAL(papszArgv[iArg+1],"POINT25D") )
447                eGType = wkbPoint25D;
448            else if( EQUAL(papszArgv[iArg+1],"LINESTRING25D") )
449                eGType = wkbLineString25D;
450            else if( EQUAL(papszArgv[iArg+1],"POLYGON25D") )
451                eGType = wkbPolygon25D;
452            else if( EQUAL(papszArgv[iArg+1],"GEOMETRYCOLLECTION25D") )
453                eGType = wkbGeometryCollection25D;
454            else if( EQUAL(papszArgv[iArg+1],"MULTIPOINT25D") )
455                eGType = wkbMultiPoint25D;
456            else if( EQUAL(papszArgv[iArg+1],"MULTILINESTRING25D") )
457                eGType = wkbMultiLineString25D;
458            else if( EQUAL(papszArgv[iArg+1],"MULTIPOLYGON25D") )
459                eGType = wkbMultiPolygon25D;
460            else
461            {
462                fprintf( stderr, "-nlt %s: type not recognised.\n", 
463                         papszArgv[iArg+1] );
464                exit( 1 );
465            }
466            iArg++;
467        }
468        else if( (EQUAL(papszArgv[iArg],"-tg") ||
469                  EQUAL(papszArgv[iArg],"-gt")) && iArg < nArgc-1 )
470        {
471            nGroupTransactions = atoi(papszArgv[++iArg]);
472        }
473        else if( EQUAL(papszArgv[iArg],"-s_srs") && iArg < nArgc-1 )
474        {
475            pszSourceSRSDef = papszArgv[++iArg];
476        }
477        else if( EQUAL(papszArgv[iArg],"-a_srs") && iArg < nArgc-1 )
478        {
479            pszOutputSRSDef = papszArgv[++iArg];
480        }
481        else if( EQUAL(papszArgv[iArg],"-t_srs") && iArg < nArgc-1 )
482        {
483            pszOutputSRSDef = papszArgv[++iArg];
484            bTransform = TRUE;
485        }
486        else if( EQUAL(papszArgv[iArg],"-spat") 
487                 && papszArgv[iArg+1] != NULL 
488                 && papszArgv[iArg+2] != NULL 
489                 && papszArgv[iArg+3] != NULL 
490                 && papszArgv[iArg+4] != NULL )
491        {
492            OGRLinearRing  oRing;
493
494            oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+2]) );
495            oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+4]) );
496            oRing.addPoint( atof(papszArgv[iArg+3]), atof(papszArgv[iArg+4]) );
497            oRing.addPoint( atof(papszArgv[iArg+3]), atof(papszArgv[iArg+2]) );
498            oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+2]) );
499
500            poSpatialFilter = new OGRPolygon();
501            ((OGRPolygon *) poSpatialFilter)->addRing( &oRing );
502            iArg += 4;
503        }
504        else if( EQUAL(papszArgv[iArg],"-where") && papszArgv[iArg+1] != NULL )
505        {
506            pszWHERE = papszArgv[++iArg];
507        }
508        else if( EQUAL(papszArgv[iArg],"-select") && papszArgv[iArg+1] != NULL)
509        {
510            pszSelect = papszArgv[++iArg];
511            papszSelFields = CSLTokenizeStringComplex(pszSelect, " ,", 
512                                                      FALSE, FALSE );
513        }
514        else if( EQUAL(papszArgv[iArg],"-segmentize") && iArg < nArgc-1 )
515        {
516            dfMaxSegmentLength = atof(papszArgv[++iArg]);
517        }
518        else if( papszArgv[iArg][0] == '-' )
519        {
520            Usage();
521        }
522        else if( pszDestDataSource == NULL )
523            pszDestDataSource = papszArgv[iArg];
524        else if( pszDataSource == NULL )
525            pszDataSource = papszArgv[iArg];
526        else
527            papszLayers = CSLAddString( papszLayers, papszArgv[iArg] );
528    }
529#endif
530
531    if( pszDataSource == NULL )
532#ifdef ZOO_SERVICE
533        {
534#endif
535          Usage();
536#ifdef ZOO_SERVICE
537          setMapInMaps(conf,"lenv","message","Wrong parameter");
538          return SERVICE_FAILED;
539        }
540#endif
541
542/* -------------------------------------------------------------------- */
543/*      Open data source.                                               */
544/* -------------------------------------------------------------------- */
545    OGRDataSource       *poDS;
546       
547    poDS = OGRSFDriverRegistrar::Open( pszDataSource, FALSE );
548
549/* -------------------------------------------------------------------- */
550/*      Report failure                                                  */
551/* -------------------------------------------------------------------- */
552    if( poDS == NULL )
553    {
554        OGRSFDriverRegistrar    *poR = OGRSFDriverRegistrar::GetRegistrar();
555       
556        fprintf( stderr, "FAILURE:\n"
557                "Unable to open datasource `%s' with the following drivers.\n",
558                pszDataSource );
559
560        for( int iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
561        {
562            fprintf( stderr, "  -> %s\n", poR->GetDriver(iDriver)->GetName() );
563        }
564#ifdef ZOO_SERVICE
565        char tmp[1024];
566        sprintf(tmp,"Unable to open datasource `%s' with the following drivers.",pszDataSource);
567        setMapInMaps(conf,"lenv","message",tmp);
568        return SERVICE_FAILED;
569#else
570        exit( 1 );
571#endif
572    }
573
574/* -------------------------------------------------------------------- */
575/*      Try opening the output datasource as an existing, writable      */
576/* -------------------------------------------------------------------- */
577    OGRDataSource       *poODS;
578   
579    if( bUpdate )
580    {
581        poODS = OGRSFDriverRegistrar::Open( pszDestDataSource, TRUE );
582        if( poODS == NULL )
583        {
584            fprintf( stderr, "FAILURE:\n"
585                    "Unable to open existing output datasource `%s'.\n",
586                    pszDestDataSource );
587#ifdef ZOO_SERVICE
588            char tmp[1024];
589            sprintf(tmp,"Unable to open existing output datasource `%s'.",pszDestDataSource);
590            setMapInMaps(conf,"lenv","message",tmp);
591            return SERVICE_FAILED;
592#else
593        exit( 1 );
594#endif
595        }
596
597        if( CSLCount(papszDSCO) > 0 )
598        {
599            fprintf( stderr, "WARNING: Datasource creation options ignored since an existing datasource\n"
600                    "         being updated.\n" );
601        }
602    }
603
604/* -------------------------------------------------------------------- */
605/*      Find the output driver.                                         */
606/* -------------------------------------------------------------------- */
607    else
608    {
609        OGRSFDriverRegistrar *poR = OGRSFDriverRegistrar::GetRegistrar();
610        OGRSFDriver          *poDriver = NULL;
611        int                  iDriver;
612
613        for( iDriver = 0;
614             iDriver < poR->GetDriverCount() && poDriver == NULL;
615             iDriver++ )
616        {
617            if( EQUAL(poR->GetDriver(iDriver)->GetName(),pszFormat) )
618            {
619                poDriver = poR->GetDriver(iDriver);
620            }
621        }
622
623        if( poDriver == NULL )
624        {
625            fprintf( stderr, "Unable to find driver `%s'.\n", pszFormat );
626            fprintf( stderr,  "The following drivers are available:\n" );
627       
628            for( iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
629            {
630                fprintf( stderr,  "  -> `%s'\n", poR->GetDriver(iDriver)->GetName() );
631            }
632#ifdef ZOO_SERVICE
633            char tmp[1024];
634            sprintf(tmp,"Unable to find driver `%s'.",pszFormat);
635            setMapInMaps(conf,"lenv","message",tmp);
636            return SERVICE_FAILED;
637#else
638            exit( 1 );
639#endif
640        }
641
642        if( !poDriver->TestCapability( ODrCCreateDataSource ) )
643        {
644            fprintf( stderr,  "%s driver does not support data source creation.\n",
645                    pszFormat );
646#ifdef ZOO_SERVICE
647            char tmp[1024];
648            sprintf(tmp,"%s driver does not support data source creation.",pszFormat);
649            setMapInMaps(conf,"lenv","message",tmp);
650            return SERVICE_FAILED;
651#else
652            exit( 1 );
653#endif
654        }
655
656/* -------------------------------------------------------------------- */
657/*      Create the output data source.                                  */
658/* -------------------------------------------------------------------- */
659        poODS = poDriver->CreateDataSource( pszDestDataSource, papszDSCO );
660        if( poODS == NULL )
661        {
662            fprintf( stderr,  "%s driver failed to create %s\n", 
663                    pszFormat, pszDestDataSource );
664#ifdef ZOO_SERVICE
665            char tmp[1024];
666            sprintf(tmp,"%s driver failed to create %s",pszFormat, pszDestDataSource);
667            setMapInMaps(conf,"lenv","message",tmp);
668            return SERVICE_FAILED;
669#else
670            exit( 1 );
671#endif
672        }
673    }
674
675/* -------------------------------------------------------------------- */
676/*      Parse the output SRS definition if possible.                    */
677/* -------------------------------------------------------------------- */
678    if( pszOutputSRSDef != NULL )
679    {
680        poOutputSRS = new OGRSpatialReference();
681        if( poOutputSRS->SetFromUserInput( pszOutputSRSDef ) != OGRERR_NONE )
682        {
683            fprintf( stderr,  "Failed to process SRS definition: %s\n", 
684                    pszOutputSRSDef );
685#ifdef ZOO_SERVICE
686            char tmp[1024];
687            sprintf(tmp,"Failed to process SRS definition: %s",pszOutputSRSDef);
688            setMapInMaps(conf,"lenv","message",tmp);
689            return SERVICE_FAILED;
690#else
691            exit( 1 );
692#endif
693        }
694    }
695
696/* -------------------------------------------------------------------- */
697/*      Parse the source SRS definition if possible.                    */
698/* -------------------------------------------------------------------- */
699    if( pszSourceSRSDef != NULL )
700    {
701        poSourceSRS = new OGRSpatialReference();
702        if( poSourceSRS->SetFromUserInput( pszSourceSRSDef ) != OGRERR_NONE )
703        {
704            fprintf( stderr,  "Failed to process SRS definition: %s\n", 
705                    pszSourceSRSDef );
706#ifdef ZOO_SERVICE
707            char tmp[1024];
708            sprintf(tmp,"Failed to process SRS definition: %s",pszOutputSRSDef);
709            setMapInMaps(conf,"lenv","message",tmp);
710            return SERVICE_FAILED;
711#else
712            exit( 1 );
713#endif
714        }
715    }
716
717/* -------------------------------------------------------------------- */
718/*      Special case for -sql clause.  No source layers required.       */
719/* -------------------------------------------------------------------- */
720    if( pszSQLStatement != NULL )
721    {
722        OGRLayer *poResultSet;
723
724        if( pszWHERE != NULL )
725            fprintf( stderr,  "-where clause ignored in combination with -sql.\n" );
726        if( CSLCount(papszLayers) > 0 )
727            fprintf( stderr,  "layer names ignored in combination with -sql.\n" );
728       
729        poResultSet = poDS->ExecuteSQL( pszSQLStatement, poSpatialFilter, 
730                                        NULL );
731
732        if( poResultSet != NULL )
733        {
734            if( !TranslateLayer( poDS, poResultSet, poODS, papszLCO, 
735                                 pszNewLayerName, bTransform, poOutputSRS,
736                                 poSourceSRS, papszSelFields, bAppend, eGType,
737                                 bOverwrite, dfMaxSegmentLength ))
738            {
739                CPLError( CE_Failure, CPLE_AppDefined, 
740                          "Terminating translation prematurely after failed\n"
741                          "translation from sql statement." );
742
743                exit( 1 );
744            }
745            poDS->ReleaseResultSet( poResultSet );
746        }
747    }
748
749/* -------------------------------------------------------------------- */
750/*      Process each data source layer.                                 */
751/* -------------------------------------------------------------------- */
752    for( int iLayer = 0; 
753         pszSQLStatement == NULL && iLayer < poDS->GetLayerCount(); 
754         iLayer++ )
755    {
756        OGRLayer        *poLayer = poDS->GetLayer(iLayer);
757
758        if( poLayer == NULL )
759        {
760            fprintf( stderr, "FAILURE: Couldn't fetch advertised layer %d!\n",
761                    iLayer );
762#ifdef ZOO_SERVICE
763            char tmp[1024];
764            sprintf(tmp,"Couldn't fetch advertised layer %d!",iLayer);
765            setMapInMaps(conf,"lenv","message",tmp);
766            return SERVICE_FAILED;
767#else
768            exit( 1 );
769#endif
770        }
771
772        if( CSLCount(papszLayers) == 0
773            || CSLFindString( papszLayers,
774                              poLayer->GetLayerDefn()->GetName() ) != -1 )
775        {
776            if( pszWHERE != NULL )
777                poLayer->SetAttributeFilter( pszWHERE );
778           
779            if( poSpatialFilter != NULL )
780                poLayer->SetSpatialFilter( poSpatialFilter );
781           
782            if( !TranslateLayer( poDS, poLayer, poODS, papszLCO, 
783                                 pszNewLayerName, bTransform, poOutputSRS,
784                                 poSourceSRS, papszSelFields, bAppend, eGType,
785                                 bOverwrite, dfMaxSegmentLength ) 
786                && !bSkipFailures )
787            {
788                CPLError( CE_Failure, CPLE_AppDefined, 
789                          "Terminating translation prematurely after failed\n"
790                          "translation of layer %s (use -skipfailures to skip errors)\n", 
791                          poLayer->GetLayerDefn()->GetName() );
792
793#ifdef ZOO_SERVICE
794                char tmp[1024];
795                sprintf(tmp,"Terminating translation prematurely after failed of layer %s",poLayer->GetLayerDefn()->GetName() );
796                setMapInMaps(conf,"lenv","message",tmp);
797                return SERVICE_FAILED;
798#else
799                exit( 1 );
800#endif
801            }
802        }
803    }
804
805/* -------------------------------------------------------------------- */
806/*      Close down.                                                     */
807/* -------------------------------------------------------------------- */
808    delete poOutputSRS;
809    delete poSourceSRS;
810    delete poODS;
811    delete poDS;
812
813    CSLDestroy(papszSelFields);
814#ifndef ZOO_SERVICE
815        CSLDestroy( papszArgv );
816#endif
817    CSLDestroy( papszLayers );
818    CSLDestroy( papszDSCO );
819    CSLDestroy( papszLCO );
820
821    OGRCleanupAll();
822
823#ifdef DBMALLOC
824    malloc_dump(1);
825#endif
826   
827#ifdef ZOO_SERVICE
828        outputs=(maps*)malloc(sizeof(maps*));
829    outputs->name="GeneratedFile";
830    outputs->content=createMap("value",(char*)pszwebDestData);
831    addMapToMap(&outputs->content,createMap("dataType","string"));
832    outputs->next=NULL;
833    return SERVICE_SUCCEEDED;
834#else
835        return 0;
836#endif
837}
838
839/************************************************************************/
840/*                               Usage()                                */
841/************************************************************************/
842
843static void Usage()
844
845{
846    OGRSFDriverRegistrar        *poR = OGRSFDriverRegistrar::GetRegistrar();
847
848#ifdef ZOO_SERVICE
849        fprintf(stderr,
850#else
851        printf(
852#endif
853                "Usage: ogr2ogr [--help-general] [-skipfailures] [-append] [-update] [-gt n]\n"
854                "               [-select field_list] [-where restricted_where] \n"
855                "               [-sql <sql statement>] \n" 
856                "               [-spat xmin ymin xmax ymax] [-preserve_fid] [-fid FID]\n"
857                "               [-a_srs srs_def] [-t_srs srs_def] [-s_srs srs_def]\n"
858                "               [-f format_name] [-overwrite] [[-dsco NAME=VALUE] ...]\n"
859                "               [-segmentize max_dist]\n"
860                "               dst_datasource_name src_datasource_name\n"
861                "               [-lco NAME=VALUE] [-nln name] [-nlt type] [layer [layer ...]]\n"
862                "\n"
863                " -f format_name: output file format name, possible values are:\n");
864   
865    for( int iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
866    {
867        OGRSFDriver *poDriver = poR->GetDriver(iDriver);
868
869        if( poDriver->TestCapability( ODrCCreateDataSource ) )
870            printf( "     -f \"%s\"\n", poDriver->GetName() );
871    }
872
873#ifdef ZOO_SERVICE
874        fprintf(stderr,
875#else
876        printf(
877#endif
878                " -append: Append to existing layer instead of creating new if it exists\n"
879                " -overwrite: delete the output layer and recreate it empty\n"
880                " -update: Open existing output datasource in update mode\n"
881                " -select field_list: Comma-delimited list of fields from input layer to\n"
882                "                     copy to the new layer (defaults to all)\n" 
883                " -where restricted_where: Attribute query (like SQL WHERE)\n" 
884                " -sql statement: Execute given SQL statement and save result.\n"
885                " -skipfailures: skip features or layers that fail to convert\n"
886                " -gt n: group n features per transaction (default 200)\n"
887                " -spat xmin ymin xmax ymax: spatial query extents\n"
888                " -segmentize max_dist: maximum distance between 2 nodes.\n"
889                "                       Used to create intermediate points\n"
890                " -dsco NAME=VALUE: Dataset creation option (format specific)\n"
891                " -lco  NAME=VALUE: Layer creation option (format specific)\n"
892                " -nln name: Assign an alternate name to the new layer\n"
893                " -nlt type: Force a geometry type for new layer.  One of NONE, GEOMETRY,\n"
894                "      POINT, LINESTRING, POLYGON, GEOMETRYCOLLECTION, MULTIPOINT,\n"
895                "      MULTIPOLYGON, or MULTILINESTRING.  Add \"25D\" for 3D layers.\n"
896                "      Default is type of source layer.\n" );
897
898#ifdef ZOO_SERVICE
899        fprintf(stderr,
900#else
901        printf(
902#endif
903                " -a_srs srs_def: Assign an output SRS\n"
904                " -t_srs srs_def: Reproject/transform to this SRS on output\n"
905                " -s_srs srs_def: Override source SRS\n"
906                "\n" 
907                " Srs_def can be a full WKT definition (hard to escape properly),\n"
908                " or a well known definition (ie. EPSG:4326) or a file with a WKT\n"
909                " definition.\n" );
910
911
912#ifndef ZOO_SERVICE
913        exit( 1 );
914#endif
915}
916
917/************************************************************************/
918/*                           TranslateLayer()                           */
919/************************************************************************/
920
921static int TranslateLayer( OGRDataSource *poSrcDS, 
922                           OGRLayer * poSrcLayer,
923                           OGRDataSource *poDstDS,
924                           char **papszLCO,
925                           const char *pszNewLayerName,
926                           int bTransform, 
927                           OGRSpatialReference *poOutputSRS,
928                           OGRSpatialReference *poSourceSRS,
929                           char **papszSelFields,
930                           int bAppend, int eGType, int bOverwrite,
931                           double dfMaxSegmentLength)
932               
933{
934    OGRLayer    *poDstLayer;
935    OGRFeatureDefn *poFDefn;
936    OGRErr      eErr;
937    int         bForceToPolygon = FALSE;
938    int         bForceToMultiPolygon = FALSE;
939
940    if( pszNewLayerName == NULL )
941        pszNewLayerName = poSrcLayer->GetLayerDefn()->GetName();
942
943    if( wkbFlatten(eGType) == wkbPolygon )
944        bForceToPolygon = TRUE;
945    else if( wkbFlatten(eGType) == wkbMultiPolygon )
946        bForceToMultiPolygon = TRUE;
947
948/* -------------------------------------------------------------------- */
949/*      Setup coordinate transformation if we need it.                  */
950/* -------------------------------------------------------------------- */
951    OGRCoordinateTransformation *poCT = NULL;
952
953    if( bTransform )
954    {
955        if( poSourceSRS == NULL )
956            poSourceSRS = poSrcLayer->GetSpatialRef();
957
958        if( poSourceSRS == NULL )
959        {
960            fprintf( stderr, "Can't transform coordinates, source layer has no\n"
961                    "coordinate system.  Use -s_srs to set one.\n" );
962#ifdef ZOO_SERVICE
963            return SERVICE_FAILED;
964#else
965            exit( 1 );
966#endif
967        }
968
969        CPLAssert( NULL != poSourceSRS );
970        CPLAssert( NULL != poOutputSRS );
971
972        poCT = OGRCreateCoordinateTransformation( poSourceSRS, poOutputSRS );
973        if( poCT == NULL )
974        {
975            char        *pszWKT = NULL;
976
977            fprintf( stderr, "Failed to create coordinate transformation between the\n"
978                   "following coordinate systems.  This may be because they\n"
979                   "are not transformable, or because projection services\n"
980                   "(PROJ.4 DLL/.so) could not be loaded.\n" );
981           
982            poSourceSRS->exportToPrettyWkt( &pszWKT, FALSE );
983            fprintf( stderr,  "Source:\n%s\n", pszWKT );
984           
985            poOutputSRS->exportToPrettyWkt( &pszWKT, FALSE );
986            fprintf( stderr,  "Target:\n%s\n", pszWKT );
987#ifdef ZOO_SERVICE
988            return SERVICE_FAILED;
989#else
990            exit( 1 );
991#endif
992        }
993    }
994   
995/* -------------------------------------------------------------------- */
996/*      Get other info.                                                 */
997/* -------------------------------------------------------------------- */
998    poFDefn = poSrcLayer->GetLayerDefn();
999   
1000    if( poOutputSRS == NULL )
1001        poOutputSRS = poSrcLayer->GetSpatialRef();
1002
1003/* -------------------------------------------------------------------- */
1004/*      Find the layer.                                                 */
1005/* -------------------------------------------------------------------- */
1006    int iLayer = -1;
1007    poDstLayer = NULL;
1008
1009    for( iLayer = 0; iLayer < poDstDS->GetLayerCount(); iLayer++ )
1010    {
1011        OGRLayer        *poLayer = poDstDS->GetLayer(iLayer);
1012
1013        if( poLayer != NULL 
1014            && EQUAL(poLayer->GetLayerDefn()->GetName(),pszNewLayerName) )
1015        {
1016            poDstLayer = poLayer;
1017            break;
1018        }
1019    }
1020   
1021/* -------------------------------------------------------------------- */
1022/*      If the user requested overwrite, and we have the layer in       */
1023/*      question we need to delete it now so it will get recreated      */
1024/*      (overwritten).                                                  */
1025/* -------------------------------------------------------------------- */
1026    if( poDstLayer != NULL && bOverwrite )
1027    {
1028        if( poDstDS->DeleteLayer( iLayer ) != OGRERR_NONE )
1029        {
1030            fprintf( stderr, 
1031                     "DeleteLayer() failed when overwrite requested.\n" );
1032            return FALSE;
1033        }
1034        poDstLayer = NULL;
1035    }
1036
1037/* -------------------------------------------------------------------- */
1038/*      If the layer does not exist, then create it.                    */
1039/* -------------------------------------------------------------------- */
1040    if( poDstLayer == NULL )
1041    {
1042        if( eGType == -2 )
1043            eGType = poFDefn->GetGeomType();
1044
1045        if( !poDstDS->TestCapability( ODsCCreateLayer ) )
1046        {
1047            fprintf( stderr, 
1048              "Layer %s not found, and CreateLayer not supported by driver.", 
1049                     pszNewLayerName );
1050            return FALSE;
1051        }
1052
1053        CPLErrorReset();
1054
1055        poDstLayer = poDstDS->CreateLayer( pszNewLayerName, poOutputSRS,
1056                                           (OGRwkbGeometryType) eGType, 
1057                                           papszLCO );
1058
1059        if( poDstLayer == NULL )
1060            return FALSE;
1061
1062        bAppend = FALSE;
1063    }
1064
1065/* -------------------------------------------------------------------- */
1066/*      Otherwise we will append to it, if append was requested.        */
1067/* -------------------------------------------------------------------- */
1068    else if( !bAppend )
1069    {
1070        fprintf( stderr, "FAILED: Layer %s already exists, and -append not specified.\n"
1071                "        Consider using -append, or -overwrite.\n",
1072                pszNewLayerName );
1073        return FALSE;
1074    }
1075    else
1076    {
1077        if( CSLCount(papszLCO) > 0 )
1078        {
1079            fprintf( stderr, "WARNING: Layer creation options ignored since an existing layer is\n"
1080                    "         being appended to.\n" );
1081        }
1082    }
1083
1084/* -------------------------------------------------------------------- */
1085/*      Add fields.  Default to copy all field.                         */
1086/*      If only a subset of all fields requested, then output only      */
1087/*      the selected fields, and in the order that they were            */
1088/*      selected.                                                       */
1089/* -------------------------------------------------------------------- */
1090    int         iField;
1091
1092    if (papszSelFields && !bAppend )
1093    {
1094        for( iField=0; papszSelFields[iField] != NULL; iField++)
1095        {
1096            int iSrcField = poFDefn->GetFieldIndex(papszSelFields[iField]);
1097            if (iSrcField >= 0)
1098                poDstLayer->CreateField( poFDefn->GetFieldDefn(iSrcField) );
1099            else
1100            {
1101                fprintf( stderr, "Field '%s' not found in source layer.\n", 
1102                        papszSelFields[iField] );
1103                if( !bSkipFailures )
1104                    return FALSE;
1105            }
1106        }
1107    }
1108    else if( !bAppend )
1109    {
1110        for( iField = 0; iField < poFDefn->GetFieldCount(); iField++ )
1111            poDstLayer->CreateField( poFDefn->GetFieldDefn(iField) );
1112    }
1113
1114/* -------------------------------------------------------------------- */
1115/*      Transfer features.                                              */
1116/* -------------------------------------------------------------------- */
1117    OGRFeature  *poFeature;
1118    int         nFeaturesInTransaction = 0;
1119   
1120    poSrcLayer->ResetReading();
1121
1122    if( nGroupTransactions )
1123        poDstLayer->StartTransaction();
1124
1125    while( TRUE )
1126    {
1127        OGRFeature      *poDstFeature = NULL;
1128
1129        if( nFIDToFetch != OGRNullFID )
1130        {
1131            // Only fetch feature on first pass.
1132            if( nFeaturesInTransaction == 0 )
1133                poFeature = poSrcLayer->GetFeature(nFIDToFetch);
1134            else
1135                poFeature = NULL;
1136        }
1137        else
1138            poFeature = poSrcLayer->GetNextFeature();
1139       
1140        if( poFeature == NULL )
1141            break;
1142
1143        if( ++nFeaturesInTransaction == nGroupTransactions )
1144        {
1145            poDstLayer->CommitTransaction();
1146            poDstLayer->StartTransaction();
1147            nFeaturesInTransaction = 0;
1148        }
1149
1150        CPLErrorReset();
1151        poDstFeature = OGRFeature::CreateFeature( poDstLayer->GetLayerDefn() );
1152
1153        if( poDstFeature->SetFrom( poFeature, TRUE ) != OGRERR_NONE )
1154        {
1155            if( nGroupTransactions )
1156                poDstLayer->CommitTransaction();
1157           
1158            CPLError( CE_Failure, CPLE_AppDefined,
1159                      "Unable to translate feature %ld from layer %s.\n",
1160                      poFeature->GetFID(), poFDefn->GetName() );
1161           
1162            OGRFeature::DestroyFeature( poFeature );
1163            OGRFeature::DestroyFeature( poDstFeature );
1164            return FALSE;
1165        }
1166
1167        if( bPreserveFID )
1168            poDstFeature->SetFID( poFeature->GetFID() );
1169
1170#ifndef GDAL_1_5_0
1171        if (poDstFeature->GetGeometryRef() != NULL && dfMaxSegmentLength > 0)
1172            poDstFeature->GetGeometryRef()->segmentize(dfMaxSegmentLength);
1173#endif
1174
1175        if( poCT && poDstFeature->GetGeometryRef() != NULL )
1176        {
1177            eErr = poDstFeature->GetGeometryRef()->transform( poCT );
1178            if( eErr != OGRERR_NONE )
1179            {
1180                if( nGroupTransactions )
1181                    poDstLayer->CommitTransaction();
1182
1183                fprintf( stderr, "Failed to reproject feature %d (geometry probably out of source or destination SRS).\n", 
1184                        (int) poFeature->GetFID() );
1185                if( !bSkipFailures )
1186                {
1187                    OGRFeature::DestroyFeature( poFeature );
1188                    OGRFeature::DestroyFeature( poDstFeature );
1189                    return FALSE;
1190                }
1191            }
1192        }
1193
1194        if( poDstFeature->GetGeometryRef() != NULL && bForceToPolygon )
1195        {
1196            poDstFeature->SetGeometryDirectly( 
1197                OGRGeometryFactory::forceToPolygon(
1198                    poDstFeature->StealGeometry() ) );
1199        }
1200                   
1201        if( poDstFeature->GetGeometryRef() != NULL && bForceToMultiPolygon )
1202        {
1203            poDstFeature->SetGeometryDirectly( 
1204                OGRGeometryFactory::forceToMultiPolygon(
1205                    poDstFeature->StealGeometry() ) );
1206        }
1207                   
1208        OGRFeature::DestroyFeature( poFeature );
1209
1210        CPLErrorReset();
1211        if( poDstLayer->CreateFeature( poDstFeature ) != OGRERR_NONE
1212            && !bSkipFailures )
1213        {
1214            if( nGroupTransactions )
1215                poDstLayer->RollbackTransaction();
1216
1217            OGRFeature::DestroyFeature( poDstFeature );
1218            return FALSE;
1219        }
1220
1221        OGRFeature::DestroyFeature( poDstFeature );
1222    }
1223
1224    if( nGroupTransactions )
1225        poDstLayer->CommitTransaction();
1226
1227/* -------------------------------------------------------------------- */
1228/*      Cleaning                                                        */
1229/* -------------------------------------------------------------------- */
1230    delete poCT;
1231
1232    return TRUE;
1233}
1234
1235#ifdef ZOO_SERVICE
1236}
1237#endif
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