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

Last change on this file since 39 was 39, checked in by djay, 13 years ago

Correct indentation.

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