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