1 : /******************************************************************************
2 : * $Id: ogr2ogr.cpp 19966 2010-07-04 20:38:02Z rouault $
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 : #include "gdal.h"
36 :
37 : CPL_CVSID("$Id: ogr2ogr.cpp 19966 2010-07-04 20:38:02Z rouault $");
38 :
39 : static void Usage();
40 :
41 5 : static int IsNumber(const char* pszStr)
42 : {
43 5 : if (*pszStr == '-' || *pszStr == '+')
44 0 : pszStr ++;
45 5 : if (*pszStr == '.')
46 0 : pszStr ++;
47 5 : return (*pszStr >= '0' && *pszStr <= '9');
48 : }
49 :
50 : static OGRGeometry* LoadGeometry( const char* pszDS,
51 : const char* pszSQL,
52 : const char* pszLyr,
53 2 : const char* pszWhere)
54 : {
55 : OGRDataSource *poDS;
56 : OGRLayer *poLyr;
57 : OGRFeature *poFeat;
58 2 : OGRGeometry *poGeom = NULL;
59 :
60 2 : poDS = OGRSFDriverRegistrar::Open( pszDS, FALSE );
61 2 : if (poDS == NULL)
62 0 : return NULL;
63 :
64 2 : if (pszSQL != NULL)
65 1 : poLyr = poDS->ExecuteSQL( pszSQL, NULL, NULL );
66 1 : else if (pszLyr != NULL)
67 0 : poLyr = poDS->GetLayerByName(pszLyr);
68 : else
69 1 : poLyr = poDS->GetLayer(0);
70 :
71 2 : if (poLyr == NULL)
72 : {
73 0 : fprintf( stderr, "Failed to identify source layer from datasource.\n" );
74 0 : OGRDataSource::DestroyDataSource(poDS);
75 0 : return NULL;
76 : }
77 :
78 2 : if (pszWhere)
79 1 : poLyr->SetAttributeFilter(pszWhere);
80 :
81 6 : while ((poFeat = poLyr->GetNextFeature()) != NULL)
82 : {
83 2 : OGRGeometry* poSrcGeom = poFeat->GetGeometryRef();
84 2 : if (poSrcGeom)
85 : {
86 2 : OGRwkbGeometryType eType = wkbFlatten( poSrcGeom->getGeometryType() );
87 :
88 2 : if (poGeom == NULL)
89 2 : poGeom = OGRGeometryFactory::createGeometry( wkbMultiPolygon );
90 :
91 2 : if( eType == wkbPolygon )
92 2 : ((OGRGeometryCollection*)poGeom)->addGeometry( poSrcGeom );
93 0 : else if( eType == wkbMultiPolygon )
94 : {
95 : int iGeom;
96 0 : int nGeomCount = OGR_G_GetGeometryCount( (OGRGeometryH)poSrcGeom );
97 :
98 0 : for( iGeom = 0; iGeom < nGeomCount; iGeom++ )
99 : {
100 : ((OGRGeometryCollection*)poGeom)->addGeometry(
101 0 : ((OGRGeometryCollection*)poSrcGeom)->getGeometryRef(iGeom) );
102 : }
103 : }
104 : else
105 : {
106 0 : fprintf( stderr, "ERROR: Geometry not of polygon type.\n" );
107 0 : OGRGeometryFactory::destroyGeometry(poGeom);
108 0 : OGRFeature::DestroyFeature(poFeat);
109 0 : if( pszSQL != NULL )
110 0 : poDS->ReleaseResultSet( poLyr );
111 0 : OGRDataSource::DestroyDataSource(poDS);
112 0 : return NULL;
113 : }
114 : }
115 :
116 2 : OGRFeature::DestroyFeature(poFeat);
117 : }
118 :
119 2 : if( pszSQL != NULL )
120 1 : poDS->ReleaseResultSet( poLyr );
121 2 : OGRDataSource::DestroyDataSource(poDS);
122 :
123 2 : return poGeom;
124 : }
125 :
126 : static int TranslateLayer( OGRDataSource *poSrcDS,
127 : OGRLayer * poSrcLayer,
128 : OGRDataSource *poDstDS,
129 : char ** papszLSCO,
130 : const char *pszNewLayerName,
131 : int bTransform,
132 : OGRSpatialReference *poOutputSRS,
133 : OGRSpatialReference *poSourceSRS,
134 : char **papszSelFields,
135 : int bAppend, int eGType,
136 : int bOverwrite,
137 : double dfMaxSegmentLength,
138 : char** papszFieldTypesToString,
139 : long nCountLayerFeatures,
140 : int bWrapDateline,
141 : OGRGeometry* poClipSrc,
142 : OGRGeometry *poClipDst,
143 : GDALProgressFunc pfnProgress,
144 : void *pProgressArg);
145 :
146 : static int bSkipFailures = FALSE;
147 : static int nGroupTransactions = 200;
148 : static int bPreserveFID = FALSE;
149 : static int nFIDToFetch = OGRNullFID;
150 :
151 : /************************************************************************/
152 : /* main() */
153 : /************************************************************************/
154 :
155 35 : int main( int nArgc, char ** papszArgv )
156 :
157 : {
158 35 : const char *pszFormat = "ESRI Shapefile";
159 35 : const char *pszDataSource = NULL;
160 35 : const char *pszDestDataSource = NULL;
161 35 : char **papszLayers = NULL;
162 35 : char **papszDSCO = NULL, **papszLCO = NULL;
163 35 : int bTransform = FALSE;
164 35 : int bAppend = FALSE, bUpdate = FALSE, bOverwrite = FALSE;
165 35 : const char *pszOutputSRSDef = NULL;
166 35 : const char *pszSourceSRSDef = NULL;
167 35 : OGRSpatialReference *poOutputSRS = NULL;
168 35 : OGRSpatialReference *poSourceSRS = NULL;
169 35 : const char *pszNewLayerName = NULL;
170 35 : const char *pszWHERE = NULL;
171 35 : OGRGeometry *poSpatialFilter = NULL;
172 : const char *pszSelect;
173 35 : char **papszSelFields = NULL;
174 35 : const char *pszSQLStatement = NULL;
175 35 : const char *pszDialect = NULL;
176 35 : int eGType = -2;
177 35 : double dfMaxSegmentLength = 0;
178 35 : char **papszFieldTypesToString = NULL;
179 35 : int bDisplayProgress = FALSE;
180 35 : GDALProgressFunc pfnProgress = NULL;
181 35 : void *pProgressArg = NULL;
182 35 : int bWrapDateline = FALSE;
183 35 : int bClipSrc = FALSE;
184 35 : OGRGeometry* poClipSrc = NULL;
185 35 : const char *pszClipSrcDS = NULL;
186 35 : const char *pszClipSrcSQL = NULL;
187 35 : const char *pszClipSrcLayer = NULL;
188 35 : const char *pszClipSrcWhere = NULL;
189 35 : OGRGeometry *poClipDst = NULL;
190 35 : const char *pszClipDstDS = NULL;
191 35 : const char *pszClipDstSQL = NULL;
192 35 : const char *pszClipDstLayer = NULL;
193 35 : const char *pszClipDstWhere = NULL;
194 :
195 : /* Check strict compilation and runtime library version as we use C++ API */
196 35 : if (! GDAL_CHECK_VERSION(papszArgv[0]))
197 0 : exit(1);
198 : /* -------------------------------------------------------------------- */
199 : /* Register format(s). */
200 : /* -------------------------------------------------------------------- */
201 35 : OGRRegisterAll();
202 :
203 : /* -------------------------------------------------------------------- */
204 : /* Processing command line arguments. */
205 : /* -------------------------------------------------------------------- */
206 35 : nArgc = OGRGeneralCmdLineProcessor( nArgc, &papszArgv, 0 );
207 :
208 35 : if( nArgc < 1 )
209 0 : exit( -nArgc );
210 :
211 156 : for( int iArg = 1; iArg < nArgc; iArg++ )
212 : {
213 122 : if( EQUAL(papszArgv[iArg], "--utility_version") )
214 : {
215 : printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
216 1 : papszArgv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
217 1 : return 0;
218 : }
219 128 : else if( EQUAL(papszArgv[iArg],"-f") && iArg < nArgc-1 )
220 : {
221 7 : pszFormat = papszArgv[++iArg];
222 : }
223 114 : else if( EQUAL(papszArgv[iArg],"-dsco") && iArg < nArgc-1 )
224 : {
225 0 : papszDSCO = CSLAddString(papszDSCO, papszArgv[++iArg] );
226 : }
227 115 : else if( EQUAL(papszArgv[iArg],"-lco") && iArg < nArgc-1 )
228 : {
229 1 : papszLCO = CSLAddString(papszLCO, papszArgv[++iArg] );
230 : }
231 113 : else if( EQUAL(papszArgv[iArg],"-preserve_fid") )
232 : {
233 0 : bPreserveFID = TRUE;
234 : }
235 113 : else if( EQUALN(papszArgv[iArg],"-skip",5) )
236 : {
237 0 : bSkipFailures = TRUE;
238 0 : nGroupTransactions = 1; /* #2409 */
239 : }
240 113 : else if( EQUAL(papszArgv[iArg],"-append") )
241 : {
242 1 : bAppend = TRUE;
243 1 : bUpdate = TRUE;
244 : }
245 112 : else if( EQUAL(papszArgv[iArg],"-overwrite") )
246 : {
247 2 : bOverwrite = TRUE;
248 2 : bUpdate = TRUE;
249 : }
250 110 : else if( EQUAL(papszArgv[iArg],"-update") )
251 : {
252 2 : bUpdate = TRUE;
253 : }
254 109 : else if( EQUAL(papszArgv[iArg],"-fid") && papszArgv[iArg+1] != NULL )
255 : {
256 1 : nFIDToFetch = atoi(papszArgv[++iArg]);
257 : }
258 112 : else if( EQUAL(papszArgv[iArg],"-sql") && papszArgv[iArg+1] != NULL )
259 : {
260 5 : pszSQLStatement = papszArgv[++iArg];
261 : }
262 102 : else if( EQUAL(papszArgv[iArg],"-dialect") && papszArgv[iArg+1] != NULL )
263 : {
264 0 : pszDialect = papszArgv[++iArg];
265 : }
266 105 : else if( EQUAL(papszArgv[iArg],"-nln") && iArg < nArgc-1 )
267 : {
268 3 : pszNewLayerName = papszArgv[++iArg];
269 : }
270 105 : else if( EQUAL(papszArgv[iArg],"-nlt") && iArg < nArgc-1 )
271 : {
272 6 : if( EQUAL(papszArgv[iArg+1],"NONE") )
273 0 : eGType = wkbNone;
274 6 : else if( EQUAL(papszArgv[iArg+1],"GEOMETRY") )
275 0 : eGType = wkbUnknown;
276 6 : else if( EQUAL(papszArgv[iArg+1],"POINT") )
277 4 : eGType = wkbPoint;
278 2 : else if( EQUAL(papszArgv[iArg+1],"LINESTRING") )
279 0 : eGType = wkbLineString;
280 2 : else if( EQUAL(papszArgv[iArg+1],"POLYGON") )
281 0 : eGType = wkbPolygon;
282 2 : else if( EQUAL(papszArgv[iArg+1],"GEOMETRYCOLLECTION") )
283 0 : eGType = wkbGeometryCollection;
284 2 : else if( EQUAL(papszArgv[iArg+1],"MULTIPOINT") )
285 0 : eGType = wkbMultiPoint;
286 2 : else if( EQUAL(papszArgv[iArg+1],"MULTILINESTRING") )
287 0 : eGType = wkbMultiLineString;
288 2 : else if( EQUAL(papszArgv[iArg+1],"MULTIPOLYGON") )
289 1 : eGType = wkbMultiPolygon;
290 1 : else if( EQUAL(papszArgv[iArg+1],"GEOMETRY25D") )
291 0 : eGType = wkbUnknown | wkb25DBit;
292 1 : else if( EQUAL(papszArgv[iArg+1],"POINT25D") )
293 0 : eGType = wkbPoint25D;
294 1 : else if( EQUAL(papszArgv[iArg+1],"LINESTRING25D") )
295 0 : eGType = wkbLineString25D;
296 1 : else if( EQUAL(papszArgv[iArg+1],"POLYGON25D") )
297 1 : eGType = wkbPolygon25D;
298 0 : else if( EQUAL(papszArgv[iArg+1],"GEOMETRYCOLLECTION25D") )
299 0 : eGType = wkbGeometryCollection25D;
300 0 : else if( EQUAL(papszArgv[iArg+1],"MULTIPOINT25D") )
301 0 : eGType = wkbMultiPoint25D;
302 0 : else if( EQUAL(papszArgv[iArg+1],"MULTILINESTRING25D") )
303 0 : eGType = wkbMultiLineString25D;
304 0 : else if( EQUAL(papszArgv[iArg+1],"MULTIPOLYGON25D") )
305 0 : eGType = wkbMultiPolygon25D;
306 : else
307 : {
308 : fprintf( stderr, "-nlt %s: type not recognised.\n",
309 0 : papszArgv[iArg+1] );
310 0 : exit( 1 );
311 : }
312 6 : iArg++;
313 : }
314 94 : else if( (EQUAL(papszArgv[iArg],"-tg") ||
315 : EQUAL(papszArgv[iArg],"-gt")) && iArg < nArgc-1 )
316 : {
317 1 : nGroupTransactions = atoi(papszArgv[++iArg]);
318 : }
319 92 : else if( EQUAL(papszArgv[iArg],"-s_srs") && iArg < nArgc-1 )
320 : {
321 0 : pszSourceSRSDef = papszArgv[++iArg];
322 : }
323 93 : else if( EQUAL(papszArgv[iArg],"-a_srs") && iArg < nArgc-1 )
324 : {
325 1 : pszOutputSRSDef = papszArgv[++iArg];
326 : }
327 93 : else if( EQUAL(papszArgv[iArg],"-t_srs") && iArg < nArgc-1 )
328 : {
329 2 : pszOutputSRSDef = papszArgv[++iArg];
330 2 : bTransform = TRUE;
331 : }
332 91 : else if( EQUAL(papszArgv[iArg],"-spat")
333 : && papszArgv[iArg+1] != NULL
334 : && papszArgv[iArg+2] != NULL
335 : && papszArgv[iArg+3] != NULL
336 : && papszArgv[iArg+4] != NULL )
337 : {
338 2 : OGRLinearRing oRing;
339 :
340 2 : oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+2]) );
341 2 : oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+4]) );
342 2 : oRing.addPoint( atof(papszArgv[iArg+3]), atof(papszArgv[iArg+4]) );
343 2 : oRing.addPoint( atof(papszArgv[iArg+3]), atof(papszArgv[iArg+2]) );
344 2 : oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+2]) );
345 :
346 2 : poSpatialFilter = new OGRPolygon();
347 2 : ((OGRPolygon *) poSpatialFilter)->addRing( &oRing );
348 2 : iArg += 4;
349 : }
350 88 : else if( EQUAL(papszArgv[iArg],"-where") && papszArgv[iArg+1] != NULL )
351 : {
352 1 : pszWHERE = papszArgv[++iArg];
353 : }
354 89 : else if( EQUAL(papszArgv[iArg],"-select") && papszArgv[iArg+1] != NULL)
355 : {
356 3 : pszSelect = papszArgv[++iArg];
357 : papszSelFields = CSLTokenizeStringComplex(pszSelect, " ,",
358 3 : FALSE, FALSE );
359 : }
360 84 : else if( EQUAL(papszArgv[iArg],"-segmentize") && iArg < nArgc-1 )
361 : {
362 1 : dfMaxSegmentLength = atof(papszArgv[++iArg]);
363 : }
364 82 : else if( EQUAL(papszArgv[iArg],"-fieldTypeToString") && iArg < nArgc-1 )
365 : {
366 : papszFieldTypesToString =
367 : CSLTokenizeStringComplex(papszArgv[++iArg], " ,",
368 0 : FALSE, FALSE );
369 0 : char** iter = papszFieldTypesToString;
370 0 : while(*iter)
371 : {
372 0 : if (EQUAL(*iter, "Integer") ||
373 : EQUAL(*iter, "Real") ||
374 : EQUAL(*iter, "String") ||
375 : EQUAL(*iter, "Date") ||
376 : EQUAL(*iter, "Time") ||
377 : EQUAL(*iter, "DateTime") ||
378 : EQUAL(*iter, "Binary") ||
379 : EQUAL(*iter, "IntegerList") ||
380 : EQUAL(*iter, "RealList") ||
381 : EQUAL(*iter, "StringList"))
382 : {
383 : /* Do nothing */
384 : }
385 0 : else if (EQUAL(*iter, "All"))
386 : {
387 0 : CSLDestroy(papszFieldTypesToString);
388 0 : papszFieldTypesToString = NULL;
389 0 : papszFieldTypesToString = CSLAddString(papszFieldTypesToString, "All");
390 0 : break;
391 : }
392 : else
393 : {
394 : fprintf(stderr, "Unhandled type for fieldtypeasstring option : %s\n",
395 0 : *iter);
396 0 : Usage();
397 : }
398 0 : iter ++;
399 : }
400 : }
401 82 : else if( EQUAL(papszArgv[iArg],"-progress") )
402 : {
403 1 : bDisplayProgress = TRUE;
404 : }
405 81 : else if( EQUAL(papszArgv[iArg],"-wrapdateline") )
406 : {
407 4 : bWrapDateline = TRUE;
408 : }
409 80 : else if( EQUAL(papszArgv[iArg],"-clipsrc") && iArg < nArgc-1 )
410 : {
411 3 : bClipSrc = TRUE;
412 3 : if ( IsNumber(papszArgv[iArg+1])
413 : && papszArgv[iArg+2] != NULL
414 : && papszArgv[iArg+3] != NULL
415 : && papszArgv[iArg+4] != NULL)
416 : {
417 0 : OGRLinearRing oRing;
418 :
419 0 : oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+2]) );
420 0 : oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+4]) );
421 0 : oRing.addPoint( atof(papszArgv[iArg+3]), atof(papszArgv[iArg+4]) );
422 0 : oRing.addPoint( atof(papszArgv[iArg+3]), atof(papszArgv[iArg+2]) );
423 0 : oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+2]) );
424 :
425 0 : poClipSrc = new OGRPolygon();
426 0 : ((OGRPolygon *) poClipSrc)->addRing( &oRing );
427 0 : iArg += 4;
428 : }
429 4 : else if (EQUALN(papszArgv[iArg+1], "POLYGON", 7) ||
430 : EQUALN(papszArgv[iArg+1], "MULTIPOLYGON", 12))
431 : {
432 1 : char* pszTmp = (char*) papszArgv[iArg+1];
433 1 : OGRGeometryFactory::createFromWkt(&pszTmp, NULL, &poClipSrc);
434 1 : if (poClipSrc == NULL)
435 : {
436 0 : fprintf( stderr, "FAILURE: Invalid geometry. Must be a valid POLYGON or MULTIPOLYGON WKT\n\n");
437 0 : Usage();
438 : }
439 1 : iArg ++;
440 : }
441 2 : else if (EQUAL(papszArgv[iArg+1], "spat_extent") )
442 : {
443 1 : iArg ++;
444 : }
445 : else
446 : {
447 1 : pszClipSrcDS = papszArgv[iArg+1];
448 1 : iArg ++;
449 : }
450 : }
451 74 : else if( EQUAL(papszArgv[iArg],"-clipsrcsql") && iArg < nArgc-1 )
452 : {
453 0 : pszClipSrcSQL = papszArgv[iArg+1];
454 0 : iArg ++;
455 : }
456 74 : else if( EQUAL(papszArgv[iArg],"-clipsrclayer") && iArg < nArgc-1 )
457 : {
458 0 : pszClipSrcLayer = papszArgv[iArg+1];
459 0 : iArg ++;
460 : }
461 75 : else if( EQUAL(papszArgv[iArg],"-clipsrcwhere") && iArg < nArgc-1 )
462 : {
463 1 : pszClipSrcWhere = papszArgv[iArg+1];
464 1 : iArg ++;
465 : }
466 75 : else if( EQUAL(papszArgv[iArg],"-clipdst") && iArg < nArgc-1 )
467 : {
468 2 : if ( IsNumber(papszArgv[iArg+1])
469 : && papszArgv[iArg+2] != NULL
470 : && papszArgv[iArg+3] != NULL
471 : && papszArgv[iArg+4] != NULL)
472 : {
473 0 : OGRLinearRing oRing;
474 :
475 0 : oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+2]) );
476 0 : oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+4]) );
477 0 : oRing.addPoint( atof(papszArgv[iArg+3]), atof(papszArgv[iArg+4]) );
478 0 : oRing.addPoint( atof(papszArgv[iArg+3]), atof(papszArgv[iArg+2]) );
479 0 : oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+2]) );
480 :
481 0 : poClipDst = new OGRPolygon();
482 0 : ((OGRPolygon *) poClipDst)->addRing( &oRing );
483 0 : iArg += 4;
484 : }
485 3 : else if (EQUALN(papszArgv[iArg+1], "POLYGON", 7) ||
486 : EQUALN(papszArgv[iArg+1], "MULTIPOLYGON", 12))
487 : {
488 1 : char* pszTmp = (char*) papszArgv[iArg+1];
489 1 : OGRGeometryFactory::createFromWkt(&pszTmp, NULL, &poClipDst);
490 1 : if (poClipDst == NULL)
491 : {
492 0 : fprintf( stderr, "FAILURE: Invalid geometry. Must be a valid POLYGON or MULTIPOLYGON WKT\n\n");
493 0 : Usage();
494 : }
495 1 : iArg ++;
496 : }
497 : else
498 : {
499 1 : pszClipDstDS = papszArgv[iArg+1];
500 1 : iArg ++;
501 : }
502 : }
503 72 : else if( EQUAL(papszArgv[iArg],"-clipdstsql") && iArg < nArgc-1 )
504 : {
505 1 : pszClipDstSQL = papszArgv[iArg+1];
506 1 : iArg ++;
507 : }
508 70 : else if( EQUAL(papszArgv[iArg],"-clipdstlayer") && iArg < nArgc-1 )
509 : {
510 0 : pszClipDstLayer = papszArgv[iArg+1];
511 0 : iArg ++;
512 : }
513 70 : else if( EQUAL(papszArgv[iArg],"-clipdstwhere") && iArg < nArgc-1 )
514 : {
515 0 : pszClipDstWhere = papszArgv[iArg+1];
516 0 : iArg ++;
517 : }
518 70 : else if( papszArgv[iArg][0] == '-' )
519 : {
520 0 : Usage();
521 : }
522 70 : else if( pszDestDataSource == NULL )
523 34 : pszDestDataSource = papszArgv[iArg];
524 36 : else if( pszDataSource == NULL )
525 34 : pszDataSource = papszArgv[iArg];
526 : else
527 2 : papszLayers = CSLAddString( papszLayers, papszArgv[iArg] );
528 : }
529 :
530 34 : if( pszDataSource == NULL )
531 0 : Usage();
532 :
533 35 : if( bClipSrc && pszClipSrcDS != NULL)
534 : {
535 1 : poClipSrc = LoadGeometry(pszClipSrcDS, pszClipSrcSQL, pszClipSrcLayer, pszClipSrcWhere);
536 1 : if (poClipSrc == NULL)
537 : {
538 0 : fprintf( stderr, "FAILURE: cannot load source clip geometry\n\n" );
539 0 : Usage();
540 : }
541 : }
542 33 : else if( bClipSrc && poClipSrc == NULL )
543 : {
544 1 : if (poSpatialFilter)
545 1 : poClipSrc = poSpatialFilter->clone();
546 1 : if (poClipSrc == NULL)
547 : {
548 : fprintf( stderr, "FAILURE: -clipsrc must be used with -spat option or a\n"
549 0 : "bounding box, WKT string or datasource must be specified\n\n");
550 0 : Usage();
551 : }
552 : }
553 :
554 34 : if( pszClipDstDS != NULL)
555 : {
556 1 : poClipDst = LoadGeometry(pszClipDstDS, pszClipDstSQL, pszClipDstLayer, pszClipDstWhere);
557 1 : if (poClipDst == NULL)
558 : {
559 0 : fprintf( stderr, "FAILURE: cannot load dest clip geometry\n\n" );
560 0 : Usage();
561 : }
562 : }
563 :
564 : /* -------------------------------------------------------------------- */
565 : /* Open data source. */
566 : /* -------------------------------------------------------------------- */
567 : OGRDataSource *poDS;
568 :
569 34 : poDS = OGRSFDriverRegistrar::Open( pszDataSource, FALSE );
570 :
571 : /* -------------------------------------------------------------------- */
572 : /* Report failure */
573 : /* -------------------------------------------------------------------- */
574 34 : if( poDS == NULL )
575 : {
576 0 : OGRSFDriverRegistrar *poR = OGRSFDriverRegistrar::GetRegistrar();
577 :
578 : fprintf( stderr, "FAILURE:\n"
579 : "Unable to open datasource `%s' with the following drivers.\n",
580 0 : pszDataSource );
581 :
582 0 : for( int iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
583 : {
584 0 : fprintf( stderr, " -> %s\n", poR->GetDriver(iDriver)->GetName() );
585 : }
586 :
587 0 : exit( 1 );
588 : }
589 :
590 : /* -------------------------------------------------------------------- */
591 : /* Try opening the output datasource as an existing, writable */
592 : /* -------------------------------------------------------------------- */
593 : OGRDataSource *poODS;
594 :
595 34 : if( bUpdate )
596 : {
597 3 : poODS = OGRSFDriverRegistrar::Open( pszDestDataSource, TRUE );
598 3 : if( poODS == NULL )
599 : {
600 : fprintf( stderr, "FAILURE:\n"
601 : "Unable to open existing output datasource `%s'.\n",
602 0 : pszDestDataSource );
603 0 : exit( 1 );
604 : }
605 :
606 3 : if( CSLCount(papszDSCO) > 0 )
607 : {
608 : fprintf( stderr, "WARNING: Datasource creation options ignored since an existing datasource\n"
609 0 : " being updated.\n" );
610 : }
611 : }
612 :
613 : /* -------------------------------------------------------------------- */
614 : /* Find the output driver. */
615 : /* -------------------------------------------------------------------- */
616 : else
617 : {
618 31 : OGRSFDriverRegistrar *poR = OGRSFDriverRegistrar::GetRegistrar();
619 31 : OGRSFDriver *poDriver = NULL;
620 : int iDriver;
621 :
622 149 : for( iDriver = 0;
623 : iDriver < poR->GetDriverCount() && poDriver == NULL;
624 : iDriver++ )
625 : {
626 118 : if( EQUAL(poR->GetDriver(iDriver)->GetName(),pszFormat) )
627 : {
628 31 : poDriver = poR->GetDriver(iDriver);
629 : }
630 : }
631 :
632 31 : if( poDriver == NULL )
633 : {
634 0 : fprintf( stderr, "Unable to find driver `%s'.\n", pszFormat );
635 0 : fprintf( stderr, "The following drivers are available:\n" );
636 :
637 0 : for( iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
638 : {
639 0 : fprintf( stderr, " -> `%s'\n", poR->GetDriver(iDriver)->GetName() );
640 : }
641 0 : exit( 1 );
642 : }
643 :
644 31 : if( !poDriver->TestCapability( ODrCCreateDataSource ) )
645 : {
646 : fprintf( stderr, "%s driver does not support data source creation.\n",
647 0 : pszFormat );
648 0 : exit( 1 );
649 : }
650 :
651 : /* -------------------------------------------------------------------- */
652 : /* Create the output data source. */
653 : /* -------------------------------------------------------------------- */
654 31 : poODS = poDriver->CreateDataSource( pszDestDataSource, papszDSCO );
655 31 : if( poODS == NULL )
656 : {
657 : fprintf( stderr, "%s driver failed to create %s\n",
658 0 : pszFormat, pszDestDataSource );
659 0 : exit( 1 );
660 : }
661 : }
662 :
663 : /* -------------------------------------------------------------------- */
664 : /* Parse the output SRS definition if possible. */
665 : /* -------------------------------------------------------------------- */
666 34 : if( pszOutputSRSDef != NULL )
667 : {
668 3 : poOutputSRS = new OGRSpatialReference();
669 3 : if( poOutputSRS->SetFromUserInput( pszOutputSRSDef ) != OGRERR_NONE )
670 : {
671 : fprintf( stderr, "Failed to process SRS definition: %s\n",
672 0 : pszOutputSRSDef );
673 0 : exit( 1 );
674 : }
675 : }
676 :
677 : /* -------------------------------------------------------------------- */
678 : /* Parse the source SRS definition if possible. */
679 : /* -------------------------------------------------------------------- */
680 34 : if( pszSourceSRSDef != NULL )
681 : {
682 0 : poSourceSRS = new OGRSpatialReference();
683 0 : if( poSourceSRS->SetFromUserInput( pszSourceSRSDef ) != OGRERR_NONE )
684 : {
685 : fprintf( stderr, "Failed to process SRS definition: %s\n",
686 0 : pszSourceSRSDef );
687 0 : exit( 1 );
688 : }
689 : }
690 :
691 : /* -------------------------------------------------------------------- */
692 : /* Special case for -sql clause. No source layers required. */
693 : /* -------------------------------------------------------------------- */
694 34 : if( pszSQLStatement != NULL )
695 : {
696 : OGRLayer *poResultSet;
697 :
698 5 : if( pszWHERE != NULL )
699 0 : fprintf( stderr, "-where clause ignored in combination with -sql.\n" );
700 5 : if( CSLCount(papszLayers) > 0 )
701 0 : fprintf( stderr, "layer names ignored in combination with -sql.\n" );
702 :
703 : poResultSet = poDS->ExecuteSQL( pszSQLStatement, poSpatialFilter,
704 5 : pszDialect );
705 :
706 5 : if( poResultSet != NULL )
707 : {
708 5 : long nCountLayerFeatures = 0;
709 5 : if (bDisplayProgress)
710 : {
711 0 : if (!poResultSet->TestCapability(OLCFastFeatureCount))
712 : {
713 0 : fprintf( stderr, "Progress turned off as fast feature count is not available.\n");
714 0 : bDisplayProgress = FALSE;
715 : }
716 : else
717 : {
718 0 : nCountLayerFeatures = poResultSet->GetFeatureCount();
719 0 : pfnProgress = GDALTermProgress;
720 : }
721 : }
722 :
723 5 : if( !TranslateLayer( poDS, poResultSet, poODS, papszLCO,
724 : pszNewLayerName, bTransform, poOutputSRS,
725 : poSourceSRS, papszSelFields, bAppend, eGType,
726 : bOverwrite, dfMaxSegmentLength, papszFieldTypesToString,
727 : nCountLayerFeatures, bWrapDateline, poClipSrc, poClipDst, pfnProgress, pProgressArg))
728 : {
729 : CPLError( CE_Failure, CPLE_AppDefined,
730 : "Terminating translation prematurely after failed\n"
731 0 : "translation from sql statement." );
732 :
733 0 : exit( 1 );
734 : }
735 5 : poDS->ReleaseResultSet( poResultSet );
736 : }
737 : }
738 :
739 : else
740 : {
741 29 : int nLayerCount = 0;
742 29 : OGRLayer** papoLayers = NULL;
743 :
744 : /* -------------------------------------------------------------------- */
745 : /* Process each data source layer. */
746 : /* -------------------------------------------------------------------- */
747 29 : if ( CSLCount(papszLayers) == 0)
748 : {
749 27 : nLayerCount = poDS->GetLayerCount();
750 27 : papoLayers = (OGRLayer**)CPLMalloc(sizeof(OGRLayer*) * nLayerCount);
751 :
752 54 : for( int iLayer = 0;
753 : iLayer < nLayerCount;
754 : iLayer++ )
755 : {
756 27 : OGRLayer *poLayer = poDS->GetLayer(iLayer);
757 :
758 27 : if( poLayer == NULL )
759 : {
760 : fprintf( stderr, "FAILURE: Couldn't fetch advertised layer %d!\n",
761 0 : iLayer );
762 0 : exit( 1 );
763 : }
764 :
765 27 : papoLayers[iLayer] = poLayer;
766 : }
767 : }
768 : /* -------------------------------------------------------------------- */
769 : /* Process specified data source layers. */
770 : /* -------------------------------------------------------------------- */
771 : else
772 : {
773 2 : nLayerCount = CSLCount(papszLayers);
774 2 : papoLayers = (OGRLayer**)CPLMalloc(sizeof(OGRLayer*) * nLayerCount);
775 :
776 4 : for( int iLayer = 0;
777 : papszLayers[iLayer] != NULL;
778 : iLayer++ )
779 : {
780 2 : OGRLayer *poLayer = poDS->GetLayerByName(papszLayers[iLayer]);
781 :
782 2 : if( poLayer == NULL )
783 : {
784 : fprintf( stderr, "FAILURE: Couldn't fetch requested layer '%s'!\n",
785 0 : papszLayers[iLayer] );
786 0 : if (!bSkipFailures)
787 0 : exit( 1 );
788 : }
789 :
790 2 : papoLayers[iLayer] = poLayer;
791 : }
792 : }
793 :
794 29 : long* panLayerCountFeatures = (long*) CPLMalloc(sizeof(long) * nLayerCount);
795 29 : long nCountLayersFeatures = 0;
796 29 : long nAccCountFeatures = 0;
797 : int iLayer;
798 :
799 : /* First pass to apply filters and count all features if necessary */
800 58 : for( iLayer = 0;
801 : iLayer < nLayerCount;
802 : iLayer++ )
803 : {
804 29 : OGRLayer *poLayer = papoLayers[iLayer];
805 29 : if (poLayer == NULL)
806 0 : continue;
807 :
808 29 : if( pszWHERE != NULL )
809 1 : poLayer->SetAttributeFilter( pszWHERE );
810 :
811 29 : if( poSpatialFilter != NULL )
812 2 : poLayer->SetSpatialFilter( poSpatialFilter );
813 :
814 29 : if (bDisplayProgress)
815 : {
816 1 : if (!poLayer->TestCapability(OLCFastFeatureCount))
817 : {
818 0 : fprintf( stderr, "Progress turned off as fast feature count is not available.\n");
819 0 : bDisplayProgress = FALSE;
820 : }
821 : else
822 : {
823 1 : panLayerCountFeatures[iLayer] = poLayer->GetFeatureCount();
824 1 : nCountLayersFeatures += panLayerCountFeatures[iLayer];
825 : }
826 : }
827 : }
828 :
829 : /* Second pass to do the real job */
830 58 : for( iLayer = 0;
831 : iLayer < nLayerCount;
832 : iLayer++ )
833 : {
834 29 : OGRLayer *poLayer = papoLayers[iLayer];
835 29 : if (poLayer == NULL)
836 0 : continue;
837 :
838 29 : if (bDisplayProgress)
839 : {
840 1 : pfnProgress = GDALScaledProgress;
841 : pProgressArg =
842 : GDALCreateScaledProgress(nAccCountFeatures * 1.0 / nCountLayersFeatures,
843 : (nAccCountFeatures + panLayerCountFeatures[iLayer]) * 1.0 / nCountLayersFeatures,
844 : GDALTermProgress,
845 1 : NULL);
846 : }
847 :
848 29 : nAccCountFeatures += panLayerCountFeatures[iLayer];
849 :
850 29 : if( !TranslateLayer( poDS, poLayer, poODS, papszLCO,
851 : pszNewLayerName, bTransform, poOutputSRS,
852 : poSourceSRS, papszSelFields, bAppend, eGType,
853 : bOverwrite, dfMaxSegmentLength, papszFieldTypesToString,
854 : panLayerCountFeatures[iLayer], bWrapDateline, poClipSrc, poClipDst, pfnProgress, pProgressArg)
855 : && !bSkipFailures )
856 : {
857 : CPLError( CE_Failure, CPLE_AppDefined,
858 : "Terminating translation prematurely after failed\n"
859 : "translation of layer %s (use -skipfailures to skip errors)\n",
860 0 : poLayer->GetLayerDefn()->GetName() );
861 :
862 0 : exit( 1 );
863 : }
864 :
865 29 : if (bDisplayProgress)
866 1 : GDALDestroyScaledProgress(pProgressArg);
867 : }
868 :
869 29 : CPLFree(panLayerCountFeatures);
870 29 : CPLFree(papoLayers);
871 : }
872 : /* -------------------------------------------------------------------- */
873 : /* Process DS style table */
874 : /* -------------------------------------------------------------------- */
875 :
876 34 : poODS->SetStyleTable( poDS->GetStyleTable () );
877 :
878 : /* -------------------------------------------------------------------- */
879 : /* Close down. */
880 : /* -------------------------------------------------------------------- */
881 34 : OGRSpatialReference::DestroySpatialReference(poOutputSRS);
882 34 : OGRSpatialReference::DestroySpatialReference(poSourceSRS);
883 34 : OGRDataSource::DestroyDataSource(poODS);
884 34 : OGRDataSource::DestroyDataSource(poDS);
885 34 : OGRGeometryFactory::destroyGeometry(poSpatialFilter);
886 34 : OGRGeometryFactory::destroyGeometry(poClipSrc);
887 34 : OGRGeometryFactory::destroyGeometry(poClipDst);
888 :
889 34 : CSLDestroy(papszSelFields);
890 34 : CSLDestroy( papszArgv );
891 34 : CSLDestroy( papszLayers );
892 34 : CSLDestroy( papszDSCO );
893 34 : CSLDestroy( papszLCO );
894 34 : CSLDestroy( papszFieldTypesToString );
895 :
896 34 : OGRCleanupAll();
897 :
898 : #ifdef DBMALLOC
899 : malloc_dump(1);
900 : #endif
901 :
902 34 : return 0;
903 : }
904 :
905 : /************************************************************************/
906 : /* Usage() */
907 : /************************************************************************/
908 :
909 0 : static void Usage()
910 :
911 : {
912 0 : OGRSFDriverRegistrar *poR = OGRSFDriverRegistrar::GetRegistrar();
913 :
914 : printf( "Usage: ogr2ogr [--help-general] [-skipfailures] [-append] [-update] [-gt n]\n"
915 : " [-select field_list] [-where restricted_where] \n"
916 : " [-progress] [-sql <sql statement>] [-dialect dialect]\n"
917 : " [-preserve_fid] [-fid FID]\n"
918 : " [-spat xmin ymin xmax ymax] [-wrapdateline]\n"
919 : " [-clipsrc [xmin ymin xmax ymax]|WKT|datasource|spat_extent] \n"
920 : " [-clipsrcsql sql_statement] [-clipsrclayer layer] \n"
921 : " [-clipsrcwhere expression]\n"
922 : " [-clipdst [xmin ymin xmax ymax]|WKT|datasource]\n"
923 : " [-clipdstsql sql_statement] [-clipdstlayer layer] \n"
924 : " [-clipdstwhere expression]\n"
925 : " [-a_srs srs_def] [-t_srs srs_def] [-s_srs srs_def]\n"
926 : " [-f format_name] [-overwrite] [[-dsco NAME=VALUE] ...]\n"
927 : " [-segmentize max_dist] [-fieldTypeToString All|(type1[,type2]*)]\n"
928 : " dst_datasource_name src_datasource_name\n"
929 : " [-lco NAME=VALUE] [-nln name] [-nlt type] [layer [layer ...]]\n"
930 : "\n"
931 0 : " -f format_name: output file format name, possible values are:\n");
932 :
933 0 : for( int iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
934 : {
935 0 : OGRSFDriver *poDriver = poR->GetDriver(iDriver);
936 :
937 0 : if( poDriver->TestCapability( ODrCCreateDataSource ) )
938 0 : printf( " -f \"%s\"\n", poDriver->GetName() );
939 : }
940 :
941 : printf( " -append: Append to existing layer instead of creating new if it exists\n"
942 : " -overwrite: delete the output layer and recreate it empty\n"
943 : " -update: Open existing output datasource in update mode\n"
944 : " -progress: Display progress on terminal. Only works if input layers have the \n"
945 : " \"fast feature count\" capability\n"
946 : " -select field_list: Comma-delimited list of fields from input layer to\n"
947 : " copy to the new layer (defaults to all)\n"
948 : " -where restricted_where: Attribute query (like SQL WHERE)\n"
949 : " -wrapdateline: split geometries crossing the dateline meridian\n"
950 : " (long. = +/- 180deg)\n"
951 : " -sql statement: Execute given SQL statement and save result.\n"
952 : " -dialect value: select a dialect, usually OGRSQL to avoid native sql.\n"
953 : " -skipfailures: skip features or layers that fail to convert\n"
954 : " -gt n: group n features per transaction (default 200)\n"
955 : " -spat xmin ymin xmax ymax: spatial query extents\n"
956 : " -segmentize max_dist: maximum distance between 2 nodes.\n"
957 : " Used to create intermediate points\n"
958 : " -dsco NAME=VALUE: Dataset creation option (format specific)\n"
959 : " -lco NAME=VALUE: Layer creation option (format specific)\n"
960 : " -nln name: Assign an alternate name to the new layer\n"
961 : " -nlt type: Force a geometry type for new layer. One of NONE, GEOMETRY,\n"
962 : " POINT, LINESTRING, POLYGON, GEOMETRYCOLLECTION, MULTIPOINT,\n"
963 : " MULTIPOLYGON, or MULTILINESTRING. Add \"25D\" for 3D layers.\n"
964 : " Default is type of source layer.\n"
965 : " -fieldTypeToString type1,...: Converts fields of specified types to\n"
966 : " fields of type string in the new layer. Valid types are : Integer,\n"
967 : " Real, String, Date, Time, DateTime, Binary, IntegerList, RealList,\n"
968 0 : " StringList. Special value All will convert all fields to strings.\n");
969 :
970 : printf(" -a_srs srs_def: Assign an output SRS\n"
971 : " -t_srs srs_def: Reproject/transform to this SRS on output\n"
972 : " -s_srs srs_def: Override source SRS\n"
973 : "\n"
974 : " Srs_def can be a full WKT definition (hard to escape properly),\n"
975 : " or a well known definition (ie. EPSG:4326) or a file with a WKT\n"
976 0 : " definition.\n" );
977 :
978 0 : exit( 1 );
979 : }
980 :
981 : /************************************************************************/
982 : /* TranslateLayer() */
983 : /************************************************************************/
984 :
985 : static int TranslateLayer( OGRDataSource *poSrcDS,
986 : OGRLayer * poSrcLayer,
987 : OGRDataSource *poDstDS,
988 : char **papszLCO,
989 : const char *pszNewLayerName,
990 : int bTransform,
991 : OGRSpatialReference *poOutputSRS,
992 : OGRSpatialReference *poSourceSRS,
993 : char **papszSelFields,
994 : int bAppend, int eGType, int bOverwrite,
995 : double dfMaxSegmentLength,
996 : char** papszFieldTypesToString,
997 : long nCountLayerFeatures,
998 : int bWrapDateline,
999 : OGRGeometry* poClipSrc,
1000 : OGRGeometry *poClipDst,
1001 : GDALProgressFunc pfnProgress,
1002 34 : void *pProgressArg)
1003 :
1004 : {
1005 : OGRLayer *poDstLayer;
1006 : OGRFeatureDefn *poSrcFDefn;
1007 34 : OGRFeatureDefn *poDstFDefn = NULL;
1008 34 : int bForceToPolygon = FALSE;
1009 34 : int bForceToMultiPolygon = FALSE;
1010 34 : int bForceToMultiLineString = FALSE;
1011 :
1012 34 : char** papszTransformOptions = NULL;
1013 :
1014 34 : if( pszNewLayerName == NULL )
1015 31 : pszNewLayerName = poSrcLayer->GetLayerDefn()->GetName();
1016 :
1017 34 : if( wkbFlatten(eGType) == wkbPolygon )
1018 1 : bForceToPolygon = TRUE;
1019 33 : else if( wkbFlatten(eGType) == wkbMultiPolygon )
1020 1 : bForceToMultiPolygon = TRUE;
1021 32 : else if( wkbFlatten(eGType) == wkbMultiLineString )
1022 0 : bForceToMultiLineString = TRUE;
1023 :
1024 : /* -------------------------------------------------------------------- */
1025 : /* Setup coordinate transformation if we need it. */
1026 : /* -------------------------------------------------------------------- */
1027 34 : OGRCoordinateTransformation *poCT = NULL;
1028 :
1029 34 : if( bTransform )
1030 : {
1031 2 : if( poSourceSRS == NULL )
1032 2 : poSourceSRS = poSrcLayer->GetSpatialRef();
1033 :
1034 2 : if( poSourceSRS == NULL )
1035 : {
1036 : fprintf( stderr, "Can't transform coordinates, source layer has no\n"
1037 0 : "coordinate system. Use -s_srs to set one.\n" );
1038 0 : exit( 1 );
1039 : }
1040 :
1041 2 : CPLAssert( NULL != poSourceSRS );
1042 2 : CPLAssert( NULL != poOutputSRS );
1043 :
1044 2 : poCT = OGRCreateCoordinateTransformation( poSourceSRS, poOutputSRS );
1045 2 : if( poCT == NULL )
1046 : {
1047 0 : char *pszWKT = NULL;
1048 :
1049 : fprintf( stderr, "Failed to create coordinate transformation between the\n"
1050 : "following coordinate systems. This may be because they\n"
1051 : "are not transformable, or because projection services\n"
1052 0 : "(PROJ.4 DLL/.so) could not be loaded.\n" );
1053 :
1054 0 : poSourceSRS->exportToPrettyWkt( &pszWKT, FALSE );
1055 0 : fprintf( stderr, "Source:\n%s\n", pszWKT );
1056 :
1057 0 : poOutputSRS->exportToPrettyWkt( &pszWKT, FALSE );
1058 0 : fprintf( stderr, "Target:\n%s\n", pszWKT );
1059 0 : exit( 1 );
1060 : }
1061 : }
1062 :
1063 34 : if (bWrapDateline)
1064 : {
1065 4 : if( poSourceSRS == NULL )
1066 3 : poSourceSRS = poSrcLayer->GetSpatialRef();
1067 :
1068 4 : if (poCT != NULL && poOutputSRS->IsGeographic())
1069 : {
1070 : papszTransformOptions =
1071 1 : CSLAddString(papszTransformOptions, "WRAPDATELINE=YES");
1072 : }
1073 3 : else if (poSourceSRS != NULL && poOutputSRS == NULL && poSourceSRS->IsGeographic())
1074 : {
1075 : papszTransformOptions =
1076 3 : CSLAddString(papszTransformOptions, "WRAPDATELINE=YES");
1077 : }
1078 : else
1079 : {
1080 0 : fprintf(stderr, "-wrapdateline option only works when reprojecting to a geographic SRS\n");
1081 : }
1082 : }
1083 :
1084 : /* -------------------------------------------------------------------- */
1085 : /* Get other info. */
1086 : /* -------------------------------------------------------------------- */
1087 34 : poSrcFDefn = poSrcLayer->GetLayerDefn();
1088 :
1089 34 : if( poOutputSRS == NULL )
1090 31 : poOutputSRS = poSrcLayer->GetSpatialRef();
1091 :
1092 : /* -------------------------------------------------------------------- */
1093 : /* Find the layer. */
1094 : /* -------------------------------------------------------------------- */
1095 34 : int iLayer = -1;
1096 34 : poDstLayer = NULL;
1097 :
1098 68 : for( iLayer = 0; iLayer < poDstDS->GetLayerCount(); iLayer++ )
1099 : {
1100 37 : OGRLayer *poLayer = poDstDS->GetLayer(iLayer);
1101 :
1102 37 : if( poLayer != NULL
1103 : && EQUAL(poLayer->GetLayerDefn()->GetName(),pszNewLayerName) )
1104 : {
1105 3 : poDstLayer = poLayer;
1106 3 : break;
1107 : }
1108 : }
1109 :
1110 : /* -------------------------------------------------------------------- */
1111 : /* If the user requested overwrite, and we have the layer in */
1112 : /* question we need to delete it now so it will get recreated */
1113 : /* (overwritten). */
1114 : /* -------------------------------------------------------------------- */
1115 34 : if( poDstLayer != NULL && bOverwrite )
1116 : {
1117 2 : if( poDstDS->DeleteLayer( iLayer ) != OGRERR_NONE )
1118 : {
1119 : fprintf( stderr,
1120 0 : "DeleteLayer() failed when overwrite requested.\n" );
1121 0 : CSLDestroy(papszTransformOptions);
1122 0 : return FALSE;
1123 : }
1124 2 : poDstLayer = NULL;
1125 : }
1126 :
1127 : /* -------------------------------------------------------------------- */
1128 : /* If the layer does not exist, then create it. */
1129 : /* -------------------------------------------------------------------- */
1130 34 : if( poDstLayer == NULL )
1131 : {
1132 33 : if( eGType == -2 )
1133 27 : eGType = poSrcFDefn->GetGeomType();
1134 :
1135 33 : if( !poDstDS->TestCapability( ODsCCreateLayer ) )
1136 : {
1137 : fprintf( stderr,
1138 : "Layer %s not found, and CreateLayer not supported by driver.",
1139 0 : pszNewLayerName );
1140 0 : return FALSE;
1141 : }
1142 :
1143 33 : CPLErrorReset();
1144 :
1145 : poDstLayer = poDstDS->CreateLayer( pszNewLayerName, poOutputSRS,
1146 : (OGRwkbGeometryType) eGType,
1147 33 : papszLCO );
1148 :
1149 33 : if( poDstLayer == NULL )
1150 : {
1151 0 : CSLDestroy(papszTransformOptions);
1152 0 : return FALSE;
1153 : }
1154 :
1155 33 : bAppend = FALSE;
1156 : }
1157 :
1158 : /* -------------------------------------------------------------------- */
1159 : /* Otherwise we will append to it, if append was requested. */
1160 : /* -------------------------------------------------------------------- */
1161 1 : else if( !bAppend )
1162 : {
1163 : fprintf( stderr, "FAILED: Layer %s already exists, and -append not specified.\n"
1164 : " Consider using -append, or -overwrite.\n",
1165 0 : pszNewLayerName );
1166 0 : return FALSE;
1167 : }
1168 : else
1169 : {
1170 1 : if( CSLCount(papszLCO) > 0 )
1171 : {
1172 : fprintf( stderr, "WARNING: Layer creation options ignored since an existing layer is\n"
1173 0 : " being appended to.\n" );
1174 : }
1175 : }
1176 :
1177 : /* -------------------------------------------------------------------- */
1178 : /* Process Layer style table */
1179 : /* -------------------------------------------------------------------- */
1180 :
1181 34 : poDstLayer->SetStyleTable( poSrcLayer->GetStyleTable () );
1182 : /* -------------------------------------------------------------------- */
1183 : /* Add fields. Default to copy all field. */
1184 : /* If only a subset of all fields requested, then output only */
1185 : /* the selected fields, and in the order that they were */
1186 : /* selected. */
1187 : /* -------------------------------------------------------------------- */
1188 34 : int nSrcFieldCount = poSrcFDefn->GetFieldCount();
1189 : int iField, *panMap;
1190 :
1191 : // Initialize the index-to-index map to -1's
1192 34 : panMap = (int *) VSIMalloc( sizeof(int) * nSrcFieldCount );
1193 136 : for( iField=0; iField < nSrcFieldCount; iField++)
1194 102 : panMap[iField] = -1;
1195 :
1196 : /* Caution : at the time of writing, the MapInfo driver */
1197 : /* returns NULL until a field has been added */
1198 34 : poDstFDefn = poDstLayer->GetLayerDefn();
1199 :
1200 37 : if (papszSelFields && !bAppend )
1201 : {
1202 3 : int nDstFieldCount = 0;
1203 3 : if (poDstFDefn)
1204 3 : nDstFieldCount = poDstFDefn->GetFieldCount();
1205 8 : for( iField=0; papszSelFields[iField] != NULL; iField++)
1206 : {
1207 5 : int iSrcField = poSrcFDefn->GetFieldIndex(papszSelFields[iField]);
1208 5 : if (iSrcField >= 0)
1209 : {
1210 5 : OGRFieldDefn* poSrcFieldDefn = poSrcFDefn->GetFieldDefn(iSrcField);
1211 5 : OGRFieldDefn oFieldDefn( poSrcFieldDefn );
1212 :
1213 5 : if (papszFieldTypesToString != NULL &&
1214 : (CSLFindString(papszFieldTypesToString, "All") != -1 ||
1215 : CSLFindString(papszFieldTypesToString,
1216 : OGRFieldDefn::GetFieldTypeName(poSrcFieldDefn->GetType())) != -1))
1217 : {
1218 0 : oFieldDefn.SetType(OFTString);
1219 : }
1220 :
1221 : /* The field may have been already created at layer creation */
1222 5 : int iDstField = -1;
1223 5 : if (poDstFDefn)
1224 5 : iDstField = poDstFDefn->GetFieldIndex(oFieldDefn.GetNameRef());
1225 5 : if (iDstField >= 0)
1226 : {
1227 0 : panMap[iSrcField] = iDstField;
1228 : }
1229 5 : else if (poDstLayer->CreateField( &oFieldDefn ) == OGRERR_NONE)
1230 : {
1231 : /* now that we've created a field, GetLayerDefn() won't return NULL */
1232 5 : if (poDstFDefn == NULL)
1233 0 : poDstFDefn = poDstLayer->GetLayerDefn();
1234 :
1235 : /* Sanity check : if it fails, the driver is buggy */
1236 5 : if (poDstFDefn != NULL &&
1237 : poDstFDefn->GetFieldCount() != nDstFieldCount + 1)
1238 : {
1239 : CPLError(CE_Warning, CPLE_AppDefined,
1240 : "The output driver has claimed to have added the %s field, but it did not!",
1241 0 : oFieldDefn.GetNameRef() );
1242 : }
1243 : else
1244 : {
1245 5 : panMap[iSrcField] = nDstFieldCount;
1246 5 : nDstFieldCount ++;
1247 : }
1248 5 : }
1249 : }
1250 : else
1251 : {
1252 : fprintf( stderr, "Field '%s' not found in source layer.\n",
1253 0 : papszSelFields[iField] );
1254 0 : if( !bSkipFailures )
1255 : {
1256 0 : VSIFree(panMap);
1257 0 : CSLDestroy(papszTransformOptions);
1258 0 : return FALSE;
1259 : }
1260 : }
1261 : }
1262 : }
1263 31 : else if( !bAppend )
1264 : {
1265 30 : int nDstFieldCount = 0;
1266 30 : if (poDstFDefn)
1267 30 : nDstFieldCount = poDstFDefn->GetFieldCount();
1268 122 : for( iField = 0; iField < nSrcFieldCount; iField++ )
1269 : {
1270 92 : OGRFieldDefn* poSrcFieldDefn = poSrcFDefn->GetFieldDefn(iField);
1271 92 : OGRFieldDefn oFieldDefn( poSrcFieldDefn );
1272 :
1273 92 : if (papszFieldTypesToString != NULL &&
1274 : (CSLFindString(papszFieldTypesToString, "All") != -1 ||
1275 : CSLFindString(papszFieldTypesToString,
1276 : OGRFieldDefn::GetFieldTypeName(poSrcFieldDefn->GetType())) != -1))
1277 : {
1278 0 : oFieldDefn.SetType(OFTString);
1279 : }
1280 :
1281 : /* The field may have been already created at layer creation */
1282 92 : int iDstField = -1;
1283 92 : if (poDstFDefn)
1284 92 : iDstField = poDstFDefn->GetFieldIndex(oFieldDefn.GetNameRef());
1285 92 : if (iDstField >= 0)
1286 : {
1287 2 : panMap[iField] = iDstField;
1288 : }
1289 90 : else if (poDstLayer->CreateField( &oFieldDefn ) == OGRERR_NONE)
1290 : {
1291 : /* now that we've created a field, GetLayerDefn() won't return NULL */
1292 90 : if (poDstFDefn == NULL)
1293 0 : poDstFDefn = poDstLayer->GetLayerDefn();
1294 :
1295 : /* Sanity check : if it fails, the driver is buggy */
1296 90 : if (poDstFDefn != NULL &&
1297 : poDstFDefn->GetFieldCount() != nDstFieldCount + 1)
1298 : {
1299 : CPLError(CE_Warning, CPLE_AppDefined,
1300 : "The output driver has claimed to have added the %s field, but it did not!",
1301 0 : oFieldDefn.GetNameRef() );
1302 : }
1303 : else
1304 : {
1305 90 : panMap[iField] = nDstFieldCount;
1306 90 : nDstFieldCount ++;
1307 : }
1308 : }
1309 : }
1310 : }
1311 : else
1312 : {
1313 : /* For an existing layer, build the map by fetching the index in the destination */
1314 : /* layer for each source field */
1315 1 : if (poDstFDefn == NULL)
1316 : {
1317 0 : fprintf( stderr, "poDstFDefn == NULL.\n" );
1318 0 : VSIFree(panMap);
1319 0 : CSLDestroy(papszTransformOptions);
1320 0 : return FALSE;
1321 : }
1322 :
1323 4 : for( iField = 0; iField < nSrcFieldCount; iField++ )
1324 : {
1325 3 : OGRFieldDefn* poSrcFieldDefn = poSrcFDefn->GetFieldDefn(iField);
1326 3 : int iDstField = poDstFDefn->GetFieldIndex(poSrcFieldDefn->GetNameRef());
1327 3 : if (iDstField >= 0)
1328 3 : panMap[iField] = iDstField;
1329 : }
1330 : }
1331 :
1332 : /* -------------------------------------------------------------------- */
1333 : /* Transfer features. */
1334 : /* -------------------------------------------------------------------- */
1335 : OGRFeature *poFeature;
1336 34 : int nFeaturesInTransaction = 0;
1337 34 : long nCount = 0;
1338 :
1339 34 : poSrcLayer->ResetReading();
1340 :
1341 34 : if( nGroupTransactions )
1342 34 : poDstLayer->StartTransaction();
1343 :
1344 229 : while( TRUE )
1345 : {
1346 263 : OGRFeature *poDstFeature = NULL;
1347 :
1348 263 : if( nFIDToFetch != OGRNullFID )
1349 : {
1350 : // Only fetch feature on first pass.
1351 2 : if( nFeaturesInTransaction == 0 )
1352 1 : poFeature = poSrcLayer->GetFeature(nFIDToFetch);
1353 : else
1354 1 : poFeature = NULL;
1355 : }
1356 : else
1357 261 : poFeature = poSrcLayer->GetNextFeature();
1358 :
1359 263 : if( poFeature == NULL )
1360 34 : break;
1361 :
1362 229 : if( ++nFeaturesInTransaction == nGroupTransactions )
1363 : {
1364 10 : poDstLayer->CommitTransaction();
1365 10 : poDstLayer->StartTransaction();
1366 10 : nFeaturesInTransaction = 0;
1367 : }
1368 :
1369 229 : CPLErrorReset();
1370 229 : poDstFeature = OGRFeature::CreateFeature( poDstLayer->GetLayerDefn() );
1371 :
1372 229 : if( poDstFeature->SetFrom( poFeature, panMap, TRUE ) != OGRERR_NONE )
1373 : {
1374 0 : if( nGroupTransactions )
1375 0 : poDstLayer->CommitTransaction();
1376 :
1377 : CPLError( CE_Failure, CPLE_AppDefined,
1378 : "Unable to translate feature %ld from layer %s.\n",
1379 0 : poFeature->GetFID(), poSrcFDefn->GetName() );
1380 :
1381 0 : OGRFeature::DestroyFeature( poFeature );
1382 0 : OGRFeature::DestroyFeature( poDstFeature );
1383 0 : VSIFree(panMap);
1384 0 : CSLDestroy(papszTransformOptions);
1385 0 : return FALSE;
1386 : }
1387 :
1388 229 : if( bPreserveFID )
1389 0 : poDstFeature->SetFID( poFeature->GetFID() );
1390 :
1391 229 : OGRGeometry* poDstGeometry = poDstFeature->GetGeometryRef();
1392 229 : if (poDstGeometry != NULL)
1393 : {
1394 228 : if (dfMaxSegmentLength > 0)
1395 10 : poDstGeometry->segmentize(dfMaxSegmentLength);
1396 :
1397 228 : if (poClipSrc)
1398 : {
1399 24 : OGRGeometry* poClipped = poDstGeometry->Intersection(poClipSrc);
1400 24 : if (poClipped == NULL || poClipped->IsEmpty())
1401 : {
1402 12 : OGRGeometryFactory::destroyGeometry(poClipped);
1403 12 : goto end_loop;
1404 : }
1405 12 : poDstFeature->SetGeometryDirectly(poClipped);
1406 12 : poDstGeometry = poClipped;
1407 : }
1408 :
1409 230 : if( poCT != NULL || papszTransformOptions != NULL)
1410 : {
1411 : OGRGeometry* poReprojectedGeom =
1412 14 : OGRGeometryFactory::transformWithOptions(poDstGeometry, poCT, papszTransformOptions);
1413 14 : if( poReprojectedGeom == NULL )
1414 : {
1415 0 : if( nGroupTransactions )
1416 0 : poDstLayer->CommitTransaction();
1417 :
1418 : fprintf( stderr, "Failed to reproject feature %d (geometry probably out of source or destination SRS).\n",
1419 0 : (int) poFeature->GetFID() );
1420 0 : if( !bSkipFailures )
1421 : {
1422 0 : OGRFeature::DestroyFeature( poFeature );
1423 0 : OGRFeature::DestroyFeature( poDstFeature );
1424 0 : VSIFree(panMap);
1425 0 : CSLDestroy(papszTransformOptions);
1426 0 : return FALSE;
1427 : }
1428 : }
1429 :
1430 14 : poDstFeature->SetGeometryDirectly(poReprojectedGeom);
1431 14 : poDstGeometry = poReprojectedGeom;
1432 : }
1433 202 : else if (poOutputSRS != NULL)
1434 : {
1435 198 : poDstGeometry->assignSpatialReference(poOutputSRS);
1436 : }
1437 :
1438 216 : if (poClipDst)
1439 : {
1440 20 : OGRGeometry* poClipped = poDstGeometry->Intersection(poClipDst);
1441 20 : if (poClipped == NULL || poClipped->IsEmpty())
1442 : {
1443 12 : OGRGeometryFactory::destroyGeometry(poClipped);
1444 12 : goto end_loop;
1445 : }
1446 :
1447 8 : poDstFeature->SetGeometryDirectly(poClipped);
1448 8 : poDstGeometry = poClipped;
1449 : }
1450 :
1451 204 : if( bForceToPolygon )
1452 : {
1453 : poDstFeature->SetGeometryDirectly(
1454 : OGRGeometryFactory::forceToPolygon(
1455 10 : poDstFeature->StealGeometry() ) );
1456 : }
1457 194 : else if( bForceToMultiPolygon )
1458 : {
1459 : poDstFeature->SetGeometryDirectly(
1460 : OGRGeometryFactory::forceToMultiPolygon(
1461 4 : poDstFeature->StealGeometry() ) );
1462 : }
1463 190 : else if ( bForceToMultiLineString )
1464 : {
1465 : poDstFeature->SetGeometryDirectly(
1466 : OGRGeometryFactory::forceToMultiLineString(
1467 0 : poDstFeature->StealGeometry() ) );
1468 : }
1469 : }
1470 :
1471 205 : CPLErrorReset();
1472 205 : if( poDstLayer->CreateFeature( poDstFeature ) != OGRERR_NONE
1473 : && !bSkipFailures )
1474 : {
1475 0 : if( nGroupTransactions )
1476 0 : poDstLayer->RollbackTransaction();
1477 :
1478 0 : OGRFeature::DestroyFeature( poFeature );
1479 0 : OGRFeature::DestroyFeature( poDstFeature );
1480 0 : VSIFree(panMap);
1481 0 : CSLDestroy(papszTransformOptions);
1482 0 : return FALSE;
1483 : }
1484 :
1485 229 : end_loop:
1486 229 : OGRFeature::DestroyFeature( poFeature );
1487 229 : OGRFeature::DestroyFeature( poDstFeature );
1488 :
1489 : /* Report progress */
1490 229 : nCount ++;
1491 229 : if (pfnProgress)
1492 10 : pfnProgress(nCount * 1.0 / nCountLayerFeatures, "", pProgressArg);
1493 : }
1494 :
1495 34 : if( nGroupTransactions )
1496 34 : poDstLayer->CommitTransaction();
1497 :
1498 : /* -------------------------------------------------------------------- */
1499 : /* Cleaning */
1500 : /* -------------------------------------------------------------------- */
1501 34 : OGRCoordinateTransformation::DestroyCT(poCT);
1502 :
1503 34 : VSIFree(panMap);
1504 34 : CSLDestroy(papszTransformOptions);
1505 :
1506 34 : return TRUE;
1507 : }
1508 :
|