1 : /******************************************************************************
2 : * $Id: ogr2ogr.cpp 25762 2013-03-16 22:50:35Z 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 : #include "gdal_alg.h"
37 : #include "commonutils.h"
38 :
39 : CPL_CVSID("$Id: ogr2ogr.cpp 25762 2013-03-16 22:50:35Z rouault $");
40 :
41 : static int bSkipFailures = FALSE;
42 : static int nGroupTransactions = 200;
43 : static int bPreserveFID = FALSE;
44 : static int nFIDToFetch = OGRNullFID;
45 :
46 : static void Usage(int bShort = TRUE);
47 : static void Usage(const char* pszAdditionalMsg, int bShort = TRUE);
48 :
49 : typedef enum
50 : {
51 : NONE,
52 : SEGMENTIZE,
53 : SIMPLIFY_PRESERVE_TOPOLOGY,
54 : } GeomOperation;
55 :
56 : typedef struct
57 : {
58 : GIntBig nFeaturesRead;
59 : int bPerFeatureCT;
60 : OGRLayer *poDstLayer;
61 : OGRCoordinateTransformation *poCT;
62 : char **papszTransformOptions;
63 : int *panMap;
64 : int iSrcZField;
65 : } TargetLayerInfo;
66 :
67 : typedef struct
68 : {
69 : OGRLayer *poSrcLayer;
70 : TargetLayerInfo *psInfo;
71 : } AssociatedLayers;
72 :
73 : static TargetLayerInfo* SetupTargetLayer( OGRDataSource *poSrcDS,
74 : OGRLayer * poSrcLayer,
75 : OGRDataSource *poDstDS,
76 : char **papszLCO,
77 : const char *pszNewLayerName,
78 : OGRSpatialReference *poOutputSRS,
79 : int bNullifyOutputSRS,
80 : char **papszSelFields,
81 : int bAppend, int eGType,
82 : int bPromoteToMulti,
83 : int nCoordDim, int bOverwrite,
84 : char** papszFieldTypesToString,
85 : int bExplodeCollections,
86 : const char* pszZField,
87 : char **papszFieldMap,
88 : const char* pszWHERE );
89 :
90 : static void FreeTargetLayerInfo(TargetLayerInfo* psInfo);
91 :
92 : static int TranslateLayer( TargetLayerInfo* psInfo,
93 : OGRDataSource *poSrcDS,
94 : OGRLayer * poSrcLayer,
95 : OGRDataSource *poDstDS,
96 : int bTransform,
97 : int bWrapDateline,
98 : const char* pszDateLineOffset,
99 : OGRSpatialReference *poOutputSRS,
100 : int bNullifyOutputSRS,
101 : OGRSpatialReference *poUserSourceSRS,
102 : OGRCoordinateTransformation *poGCPCoordTrans,
103 : int eGType,
104 : int bPromoteToMulti,
105 : int nCoordDim,
106 : GeomOperation eGeomOp,
107 : double dfGeomOpParam,
108 : long nCountLayerFeatures,
109 : OGRGeometry* poClipSrc,
110 : OGRGeometry *poClipDst,
111 : int bExplodeCollections,
112 : vsi_l_offset nSrcFileSize,
113 : GIntBig* pnReadFeatureCount,
114 : GDALProgressFunc pfnProgress,
115 : void *pProgressArg);
116 :
117 : /* -------------------------------------------------------------------- */
118 : /* CheckDestDataSourceNameConsistency() */
119 : /* -------------------------------------------------------------------- */
120 :
121 : static
122 43 : void CheckDestDataSourceNameConsistency(const char* pszDestFilename,
123 : const char* pszDriverName)
124 : {
125 : int i;
126 43 : char* pszDestExtension = CPLStrdup(CPLGetExtension(pszDestFilename));
127 :
128 : /* TODO: Would be good to have driver metadata like for GDAL drivers ! */
129 : static const char* apszExtensions[][2] = { { "shp" , "ESRI Shapefile" },
130 : { "dbf" , "ESRI Shapefile" },
131 : { "sqlite" , "SQLite" },
132 : { "db" , "SQLite" },
133 : { "mif" , "MapInfo File" },
134 : { "tab" , "MapInfo File" },
135 : { "s57" , "S57" },
136 : { "bna" , "BNA" },
137 : { "csv" , "CSV" },
138 : { "gml" , "GML" },
139 : { "kml" , "KML/LIBKML" },
140 : { "kmz" , "LIBKML" },
141 : { "json" , "GeoJSON" },
142 : { "geojson", "GeoJSON" },
143 : { "dxf" , "DXF" },
144 : { "gdb" , "FileGDB" },
145 : { "pix" , "PCIDSK" },
146 : { "sql" , "PGDump" },
147 : { "gtm" , "GPSTrackMaker" },
148 : { "gmt" , "GMT" },
149 : { "pdf" , "PDF" },
150 : { NULL, NULL }
151 : };
152 : static const char* apszBeginName[][2] = { { "PG:" , "PG" },
153 : { "MySQL:" , "MySQL" },
154 : { "CouchDB:" , "CouchDB" },
155 : { "GFT:" , "GFT" },
156 : { "MSSQL:" , "MSSQLSpatial" },
157 : { "ODBC:" , "ODBC" },
158 : { "OCI:" , "OCI" },
159 : { "SDE:" , "SDE" },
160 : { "WFS:" , "WFS" },
161 : { NULL, NULL }
162 : };
163 :
164 946 : for(i=0; apszExtensions[i][0] != NULL; i++)
165 : {
166 903 : if (EQUAL(pszDestExtension, apszExtensions[i][0]) && !EQUAL(pszDriverName, apszExtensions[i][1]))
167 : {
168 : fprintf(stderr,
169 : "Warning: The target file has a '%s' extension, which is normally used by the %s driver,\n"
170 : "but the requested output driver is %s. Is it really what you want ?\n",
171 : pszDestExtension,
172 : apszExtensions[i][1],
173 0 : pszDriverName);
174 0 : break;
175 : }
176 : }
177 :
178 430 : for(i=0; apszBeginName[i][0] != NULL; i++)
179 : {
180 387 : if (EQUALN(pszDestFilename, apszBeginName[i][0], strlen(apszBeginName[i][0])) &&
181 : !EQUAL(pszDriverName, apszBeginName[i][1]))
182 : {
183 : fprintf(stderr,
184 : "Warning: The target file has a name which is normally recognized by the %s driver,\n"
185 : "but the requested output driver is %s. Is it really what you want ?\n",
186 : apszBeginName[i][1],
187 0 : pszDriverName);
188 0 : break;
189 : }
190 : }
191 :
192 43 : CPLFree(pszDestExtension);
193 43 : }
194 :
195 : /************************************************************************/
196 : /* IsNumber() */
197 : /************************************************************************/
198 :
199 5 : static int IsNumber(const char* pszStr)
200 : {
201 5 : if (*pszStr == '-' || *pszStr == '+')
202 0 : pszStr ++;
203 5 : if (*pszStr == '.')
204 0 : pszStr ++;
205 5 : return (*pszStr >= '0' && *pszStr <= '9');
206 : }
207 :
208 : /************************************************************************/
209 : /* LoadGeometry() */
210 : /************************************************************************/
211 :
212 2 : static OGRGeometry* LoadGeometry( const char* pszDS,
213 : const char* pszSQL,
214 : const char* pszLyr,
215 : const char* pszWhere)
216 : {
217 : OGRDataSource *poDS;
218 : OGRLayer *poLyr;
219 : OGRFeature *poFeat;
220 2 : OGRGeometry *poGeom = NULL;
221 :
222 2 : poDS = OGRSFDriverRegistrar::Open( pszDS, FALSE );
223 2 : if (poDS == NULL)
224 0 : return NULL;
225 :
226 2 : if (pszSQL != NULL)
227 1 : poLyr = poDS->ExecuteSQL( pszSQL, NULL, NULL );
228 1 : else if (pszLyr != NULL)
229 0 : poLyr = poDS->GetLayerByName(pszLyr);
230 : else
231 1 : poLyr = poDS->GetLayer(0);
232 :
233 2 : if (poLyr == NULL)
234 : {
235 0 : fprintf( stderr, "Failed to identify source layer from datasource.\n" );
236 0 : OGRDataSource::DestroyDataSource(poDS);
237 0 : return NULL;
238 : }
239 :
240 2 : if (pszWhere)
241 1 : poLyr->SetAttributeFilter(pszWhere);
242 :
243 6 : while ((poFeat = poLyr->GetNextFeature()) != NULL)
244 : {
245 2 : OGRGeometry* poSrcGeom = poFeat->GetGeometryRef();
246 2 : if (poSrcGeom)
247 : {
248 2 : OGRwkbGeometryType eType = wkbFlatten( poSrcGeom->getGeometryType() );
249 :
250 2 : if (poGeom == NULL)
251 2 : poGeom = OGRGeometryFactory::createGeometry( wkbMultiPolygon );
252 :
253 2 : if( eType == wkbPolygon )
254 2 : ((OGRGeometryCollection*)poGeom)->addGeometry( poSrcGeom );
255 0 : else if( eType == wkbMultiPolygon )
256 : {
257 : int iGeom;
258 0 : int nGeomCount = OGR_G_GetGeometryCount( (OGRGeometryH)poSrcGeom );
259 :
260 0 : for( iGeom = 0; iGeom < nGeomCount; iGeom++ )
261 : {
262 : ((OGRGeometryCollection*)poGeom)->addGeometry(
263 0 : ((OGRGeometryCollection*)poSrcGeom)->getGeometryRef(iGeom) );
264 : }
265 : }
266 : else
267 : {
268 0 : fprintf( stderr, "ERROR: Geometry not of polygon type.\n" );
269 0 : OGRGeometryFactory::destroyGeometry(poGeom);
270 0 : OGRFeature::DestroyFeature(poFeat);
271 0 : if( pszSQL != NULL )
272 0 : poDS->ReleaseResultSet( poLyr );
273 0 : OGRDataSource::DestroyDataSource(poDS);
274 0 : return NULL;
275 : }
276 : }
277 :
278 2 : OGRFeature::DestroyFeature(poFeat);
279 : }
280 :
281 2 : if( pszSQL != NULL )
282 1 : poDS->ReleaseResultSet( poLyr );
283 2 : OGRDataSource::DestroyDataSource(poDS);
284 :
285 2 : return poGeom;
286 : }
287 :
288 :
289 : /************************************************************************/
290 : /* OGRSplitListFieldLayer */
291 : /************************************************************************/
292 :
293 : typedef struct
294 : {
295 : int iSrcIndex;
296 : OGRFieldType eType;
297 : int nMaxOccurences;
298 : int nWidth;
299 : } ListFieldDesc;
300 :
301 : class OGRSplitListFieldLayer : public OGRLayer
302 : {
303 : OGRLayer *poSrcLayer;
304 : OGRFeatureDefn *poFeatureDefn;
305 : ListFieldDesc *pasListFields;
306 : int nListFieldCount;
307 : int nMaxSplitListSubFields;
308 :
309 : OGRFeature *TranslateFeature(OGRFeature* poSrcFeature);
310 :
311 : public:
312 : OGRSplitListFieldLayer(OGRLayer* poSrcLayer,
313 : int nMaxSplitListSubFields);
314 : ~OGRSplitListFieldLayer();
315 :
316 : int BuildLayerDefn(GDALProgressFunc pfnProgress,
317 : void *pProgressArg);
318 :
319 : virtual OGRFeature *GetNextFeature();
320 : virtual OGRFeature *GetFeature(long nFID);
321 : virtual OGRFeatureDefn *GetLayerDefn();
322 :
323 1 : virtual void ResetReading() { poSrcLayer->ResetReading(); }
324 0 : virtual int TestCapability(const char*) { return FALSE; }
325 :
326 0 : virtual int GetFeatureCount( int bForce = TRUE )
327 : {
328 0 : return poSrcLayer->GetFeatureCount(bForce);
329 : }
330 :
331 2 : virtual OGRSpatialReference *GetSpatialRef()
332 : {
333 2 : return poSrcLayer->GetSpatialRef();
334 : }
335 :
336 0 : virtual OGRGeometry *GetSpatialFilter()
337 : {
338 0 : return poSrcLayer->GetSpatialFilter();
339 : }
340 :
341 1 : virtual OGRStyleTable *GetStyleTable()
342 : {
343 1 : return poSrcLayer->GetStyleTable();
344 : }
345 :
346 0 : virtual void SetSpatialFilter( OGRGeometry *poGeom )
347 : {
348 0 : poSrcLayer->SetSpatialFilter(poGeom);
349 0 : }
350 :
351 0 : virtual void SetSpatialFilterRect( double dfMinX, double dfMinY,
352 : double dfMaxX, double dfMaxY )
353 : {
354 0 : poSrcLayer->SetSpatialFilterRect(dfMinX, dfMinY, dfMaxX, dfMaxY);
355 0 : }
356 :
357 0 : virtual OGRErr SetAttributeFilter( const char *pszFilter )
358 : {
359 0 : return poSrcLayer->SetAttributeFilter(pszFilter);
360 : }
361 : };
362 :
363 : /************************************************************************/
364 : /* OGRSplitListFieldLayer() */
365 : /************************************************************************/
366 :
367 1 : OGRSplitListFieldLayer::OGRSplitListFieldLayer(OGRLayer* poSrcLayer,
368 1 : int nMaxSplitListSubFields)
369 : {
370 1 : this->poSrcLayer = poSrcLayer;
371 1 : if (nMaxSplitListSubFields < 0)
372 1 : nMaxSplitListSubFields = INT_MAX;
373 1 : this->nMaxSplitListSubFields = nMaxSplitListSubFields;
374 1 : poFeatureDefn = NULL;
375 1 : pasListFields = NULL;
376 1 : nListFieldCount = 0;
377 1 : }
378 :
379 : /************************************************************************/
380 : /* ~OGRSplitListFieldLayer() */
381 : /************************************************************************/
382 :
383 1 : OGRSplitListFieldLayer::~OGRSplitListFieldLayer()
384 : {
385 1 : if( poFeatureDefn )
386 1 : poFeatureDefn->Release();
387 :
388 1 : CPLFree(pasListFields);
389 1 : }
390 :
391 : /************************************************************************/
392 : /* BuildLayerDefn() */
393 : /************************************************************************/
394 :
395 1 : int OGRSplitListFieldLayer::BuildLayerDefn(GDALProgressFunc pfnProgress,
396 : void *pProgressArg)
397 : {
398 1 : CPLAssert(poFeatureDefn == NULL);
399 :
400 1 : OGRFeatureDefn* poSrcFieldDefn = poSrcLayer->GetLayerDefn();
401 :
402 1 : int nSrcFields = poSrcFieldDefn->GetFieldCount();
403 : pasListFields =
404 1 : (ListFieldDesc*)CPLCalloc(sizeof(ListFieldDesc), nSrcFields);
405 1 : nListFieldCount = 0;
406 : int i;
407 :
408 : /* Establish the list of fields of list type */
409 6 : for(i=0;i<nSrcFields;i++)
410 : {
411 5 : OGRFieldType eType = poSrcFieldDefn->GetFieldDefn(i)->GetType();
412 5 : if (eType == OFTIntegerList ||
413 : eType == OFTRealList ||
414 : eType == OFTStringList)
415 : {
416 3 : pasListFields[nListFieldCount].iSrcIndex = i;
417 3 : pasListFields[nListFieldCount].eType = eType;
418 3 : if (nMaxSplitListSubFields == 1)
419 0 : pasListFields[nListFieldCount].nMaxOccurences = 1;
420 3 : nListFieldCount++;
421 : }
422 : }
423 :
424 1 : if (nListFieldCount == 0)
425 0 : return FALSE;
426 :
427 : /* No need for full scan if the limit is 1. We just to have to create */
428 : /* one and a single one field */
429 1 : if (nMaxSplitListSubFields != 1)
430 : {
431 1 : poSrcLayer->ResetReading();
432 : OGRFeature* poSrcFeature;
433 :
434 1 : int nFeatureCount = 0;
435 1 : if (poSrcLayer->TestCapability(OLCFastFeatureCount))
436 1 : nFeatureCount = poSrcLayer->GetFeatureCount();
437 1 : int nFeatureIndex = 0;
438 :
439 : /* Scan the whole layer to compute the maximum number of */
440 : /* items for each field of list type */
441 3 : while( (poSrcFeature = poSrcLayer->GetNextFeature()) != NULL )
442 : {
443 4 : for(i=0;i<nListFieldCount;i++)
444 : {
445 3 : int nCount = 0;
446 : OGRField* psField =
447 3 : poSrcFeature->GetRawFieldRef(pasListFields[i].iSrcIndex);
448 3 : switch(pasListFields[i].eType)
449 : {
450 : case OFTIntegerList:
451 1 : nCount = psField->IntegerList.nCount;
452 1 : break;
453 : case OFTRealList:
454 1 : nCount = psField->RealList.nCount;
455 1 : break;
456 : case OFTStringList:
457 : {
458 1 : nCount = psField->StringList.nCount;
459 1 : char** paList = psField->StringList.paList;
460 : int j;
461 3 : for(j=0;j<nCount;j++)
462 : {
463 2 : int nWidth = strlen(paList[j]);
464 2 : if (nWidth > pasListFields[i].nWidth)
465 1 : pasListFields[i].nWidth = nWidth;
466 : }
467 1 : break;
468 : }
469 : default:
470 0 : CPLAssert(0);
471 : break;
472 : }
473 3 : if (nCount > pasListFields[i].nMaxOccurences)
474 : {
475 3 : if (nCount > nMaxSplitListSubFields)
476 0 : nCount = nMaxSplitListSubFields;
477 3 : pasListFields[i].nMaxOccurences = nCount;
478 : }
479 : }
480 1 : OGRFeature::DestroyFeature(poSrcFeature);
481 :
482 1 : nFeatureIndex ++;
483 1 : if (pfnProgress != NULL && nFeatureCount != 0)
484 0 : pfnProgress(nFeatureIndex * 1.0 / nFeatureCount, "", pProgressArg);
485 : }
486 : }
487 :
488 : /* Now let's build the target feature definition */
489 :
490 : poFeatureDefn =
491 1 : OGRFeatureDefn::CreateFeatureDefn( poSrcFieldDefn->GetName() );
492 1 : poFeatureDefn->Reference();
493 1 : poFeatureDefn->SetGeomType( poSrcFieldDefn->GetGeomType() );
494 :
495 1 : int iListField = 0;
496 6 : for(i=0;i<nSrcFields;i++)
497 : {
498 5 : OGRFieldType eType = poSrcFieldDefn->GetFieldDefn(i)->GetType();
499 8 : if (eType == OFTIntegerList ||
500 : eType == OFTRealList ||
501 : eType == OFTStringList)
502 : {
503 3 : int nMaxOccurences = pasListFields[iListField].nMaxOccurences;
504 3 : int nWidth = pasListFields[iListField].nWidth;
505 3 : iListField ++;
506 : int j;
507 3 : if (nMaxOccurences == 1)
508 : {
509 : OGRFieldDefn oFieldDefn(poSrcFieldDefn->GetFieldDefn(i)->GetNameRef(),
510 : (eType == OFTIntegerList) ? OFTInteger :
511 : (eType == OFTRealList) ? OFTReal :
512 0 : OFTString);
513 0 : poFeatureDefn->AddFieldDefn(&oFieldDefn);
514 : }
515 : else
516 : {
517 9 : for(j=0;j<nMaxOccurences;j++)
518 : {
519 6 : CPLString osFieldName;
520 : osFieldName.Printf("%s%d",
521 6 : poSrcFieldDefn->GetFieldDefn(i)->GetNameRef(), j+1);
522 : OGRFieldDefn oFieldDefn(osFieldName.c_str(),
523 : (eType == OFTIntegerList) ? OFTInteger :
524 : (eType == OFTRealList) ? OFTReal :
525 6 : OFTString);
526 6 : oFieldDefn.SetWidth(nWidth);
527 6 : poFeatureDefn->AddFieldDefn(&oFieldDefn);
528 : }
529 : }
530 : }
531 : else
532 : {
533 2 : poFeatureDefn->AddFieldDefn(poSrcFieldDefn->GetFieldDefn(i));
534 : }
535 : }
536 :
537 1 : return TRUE;
538 : }
539 :
540 :
541 : /************************************************************************/
542 : /* TranslateFeature() */
543 : /************************************************************************/
544 :
545 2 : OGRFeature *OGRSplitListFieldLayer::TranslateFeature(OGRFeature* poSrcFeature)
546 : {
547 2 : if (poSrcFeature == NULL)
548 1 : return NULL;
549 1 : if (poFeatureDefn == NULL)
550 0 : return poSrcFeature;
551 :
552 1 : OGRFeature* poFeature = OGRFeature::CreateFeature(poFeatureDefn);
553 1 : poFeature->SetFID(poSrcFeature->GetFID());
554 1 : poFeature->SetGeometryDirectly(poSrcFeature->StealGeometry());
555 1 : poFeature->SetStyleString(poFeature->GetStyleString());
556 :
557 1 : OGRFeatureDefn* poSrcFieldDefn = poSrcLayer->GetLayerDefn();
558 1 : int nSrcFields = poSrcFeature->GetFieldCount();
559 : int iSrcField;
560 1 : int iDstField = 0;
561 1 : int iListField = 0;
562 : int j;
563 6 : for(iSrcField=0;iSrcField<nSrcFields;iSrcField++)
564 : {
565 5 : OGRFieldType eType = poSrcFieldDefn->GetFieldDefn(iSrcField)->GetType();
566 5 : OGRField* psField = poSrcFeature->GetRawFieldRef(iSrcField);
567 5 : switch(eType)
568 : {
569 : case OFTIntegerList:
570 : {
571 1 : int nCount = psField->IntegerList.nCount;
572 1 : if (nCount > nMaxSplitListSubFields)
573 0 : nCount = nMaxSplitListSubFields;
574 1 : int* paList = psField->IntegerList.paList;
575 3 : for(j=0;j<nCount;j++)
576 2 : poFeature->SetField(iDstField + j, paList[j]);
577 1 : iDstField += pasListFields[iListField].nMaxOccurences;
578 1 : iListField++;
579 1 : break;
580 : }
581 : case OFTRealList:
582 : {
583 1 : int nCount = psField->RealList.nCount;
584 1 : if (nCount > nMaxSplitListSubFields)
585 0 : nCount = nMaxSplitListSubFields;
586 1 : double* paList = psField->RealList.paList;
587 3 : for(j=0;j<nCount;j++)
588 2 : poFeature->SetField(iDstField + j, paList[j]);
589 1 : iDstField += pasListFields[iListField].nMaxOccurences;
590 1 : iListField++;
591 1 : break;
592 : }
593 : case OFTStringList:
594 : {
595 1 : int nCount = psField->StringList.nCount;
596 1 : if (nCount > nMaxSplitListSubFields)
597 0 : nCount = nMaxSplitListSubFields;
598 1 : char** paList = psField->StringList.paList;
599 3 : for(j=0;j<nCount;j++)
600 2 : poFeature->SetField(iDstField + j, paList[j]);
601 1 : iDstField += pasListFields[iListField].nMaxOccurences;
602 1 : iListField++;
603 1 : break;
604 : }
605 : default:
606 2 : poFeature->SetField(iDstField, psField);
607 2 : iDstField ++;
608 : break;
609 : }
610 : }
611 :
612 1 : OGRFeature::DestroyFeature(poSrcFeature);
613 :
614 1 : return poFeature;
615 : }
616 :
617 : /************************************************************************/
618 : /* GetNextFeature() */
619 : /************************************************************************/
620 :
621 2 : OGRFeature *OGRSplitListFieldLayer::GetNextFeature()
622 : {
623 2 : return TranslateFeature(poSrcLayer->GetNextFeature());
624 : }
625 :
626 : /************************************************************************/
627 : /* GetFeature() */
628 : /************************************************************************/
629 :
630 0 : OGRFeature *OGRSplitListFieldLayer::GetFeature(long nFID)
631 : {
632 0 : return TranslateFeature(poSrcLayer->GetFeature(nFID));
633 : }
634 :
635 : /************************************************************************/
636 : /* GetLayerDefn() */
637 : /************************************************************************/
638 :
639 2 : OGRFeatureDefn* OGRSplitListFieldLayer::GetLayerDefn()
640 : {
641 2 : if (poFeatureDefn == NULL)
642 0 : return poSrcLayer->GetLayerDefn();
643 2 : return poFeatureDefn;
644 : }
645 :
646 : /************************************************************************/
647 : /* GCPCoordTransformation() */
648 : /* */
649 : /* Apply GCP Transform to points */
650 : /************************************************************************/
651 :
652 : class GCPCoordTransformation : public OGRCoordinateTransformation
653 : {
654 : public:
655 :
656 : void *hTransformArg;
657 : int bUseTPS;
658 : OGRSpatialReference* poSRS;
659 :
660 5 : GCPCoordTransformation( int nGCPCount,
661 : const GDAL_GCP *pasGCPList,
662 : int nReqOrder,
663 : OGRSpatialReference* poSRS)
664 5 : {
665 5 : if( nReqOrder < 0 )
666 : {
667 1 : bUseTPS = TRUE;
668 : hTransformArg =
669 1 : GDALCreateTPSTransformer( nGCPCount, pasGCPList, FALSE );
670 : }
671 : else
672 : {
673 4 : bUseTPS = FALSE;
674 : hTransformArg =
675 4 : GDALCreateGCPTransformer( nGCPCount, pasGCPList, nReqOrder, FALSE );
676 : }
677 5 : this->poSRS = poSRS;
678 5 : if( poSRS)
679 2 : poSRS->Reference();
680 5 : }
681 :
682 5 : int IsValid() const { return hTransformArg != NULL; }
683 :
684 5 : virtual ~GCPCoordTransformation()
685 5 : {
686 5 : if( hTransformArg != NULL )
687 : {
688 5 : if( bUseTPS )
689 1 : GDALDestroyTPSTransformer(hTransformArg);
690 : else
691 4 : GDALDestroyGCPTransformer(hTransformArg);
692 : }
693 5 : if( poSRS)
694 2 : poSRS->Dereference();
695 5 : }
696 :
697 0 : virtual OGRSpatialReference *GetSourceCS() { return poSRS; }
698 8 : virtual OGRSpatialReference *GetTargetCS() { return poSRS; }
699 :
700 10 : virtual int Transform( int nCount,
701 : double *x, double *y, double *z = NULL )
702 : {
703 10 : int *pabSuccess = (int *) CPLMalloc(sizeof(int) * nCount );
704 : int bOverallSuccess, i;
705 :
706 10 : bOverallSuccess = TransformEx( nCount, x, y, z, pabSuccess );
707 :
708 20 : for( i = 0; i < nCount; i++ )
709 : {
710 10 : if( !pabSuccess[i] )
711 : {
712 0 : bOverallSuccess = FALSE;
713 0 : break;
714 : }
715 : }
716 :
717 10 : CPLFree( pabSuccess );
718 :
719 10 : return bOverallSuccess;
720 : }
721 :
722 10 : virtual int TransformEx( int nCount,
723 : double *x, double *y, double *z = NULL,
724 : int *pabSuccess = NULL )
725 : {
726 10 : if( bUseTPS )
727 : return GDALTPSTransform( hTransformArg, FALSE,
728 2 : nCount, x, y, z, pabSuccess );
729 : else
730 : return GDALGCPTransform( hTransformArg, FALSE,
731 8 : nCount, x, y, z, pabSuccess );
732 : }
733 : };
734 :
735 : /************************************************************************/
736 : /* CompositeCT */
737 : /************************************************************************/
738 :
739 : class CompositeCT : public OGRCoordinateTransformation
740 : {
741 : public:
742 :
743 : OGRCoordinateTransformation* poCT1;
744 : OGRCoordinateTransformation* poCT2;
745 :
746 1 : CompositeCT( OGRCoordinateTransformation* poCT1, /* will not be deleted */
747 : OGRCoordinateTransformation* poCT2 /* deleted with OGRCoordinateTransformation::DestroyCT() */ )
748 1 : {
749 1 : this->poCT1 = poCT1;
750 1 : this->poCT2 = poCT2;
751 1 : }
752 :
753 1 : virtual ~CompositeCT()
754 1 : {
755 1 : OGRCoordinateTransformation::DestroyCT(poCT2);
756 1 : }
757 :
758 0 : virtual OGRSpatialReference *GetSourceCS()
759 : {
760 0 : return poCT1 ? poCT1->GetSourceCS() :
761 0 : poCT2 ? poCT2->GetSourceCS() : NULL;
762 : }
763 :
764 2 : virtual OGRSpatialReference *GetTargetCS()
765 : {
766 2 : return poCT2 ? poCT2->GetTargetCS() :
767 4 : poCT1 ? poCT1->GetTargetCS() : NULL;
768 : }
769 :
770 2 : virtual int Transform( int nCount,
771 : double *x, double *y, double *z = NULL )
772 : {
773 2 : int nResult = TRUE;
774 2 : if( poCT1 )
775 2 : nResult = poCT1->Transform(nCount, x, y, z);
776 2 : if( nResult && poCT2 )
777 2 : nResult = poCT2->Transform(nCount, x, y, z);
778 2 : return nResult;
779 : }
780 :
781 0 : virtual int TransformEx( int nCount,
782 : double *x, double *y, double *z = NULL,
783 : int *pabSuccess = NULL )
784 : {
785 0 : int nResult = TRUE;
786 0 : if( poCT1 )
787 0 : nResult = poCT1->TransformEx(nCount, x, y, z, pabSuccess);
788 0 : if( nResult && poCT2 )
789 0 : nResult = poCT2->TransformEx(nCount, x, y, z, pabSuccess);
790 0 : return nResult;
791 : }
792 : };
793 :
794 : /************************************************************************/
795 : /* main() */
796 : /************************************************************************/
797 :
798 : #define CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(nExtraArg) \
799 : do { if (iArg + nExtraArg >= nArgc) \
800 : Usage(CPLSPrintf("%s option requires %d argument(s)", papszArgv[iArg], nExtraArg)); } while(0)
801 :
802 91 : int main( int nArgc, char ** papszArgv )
803 :
804 : {
805 91 : int nRetCode = 0;
806 91 : int bQuiet = FALSE;
807 91 : int bFormatExplicitelySet = FALSE;
808 91 : const char *pszFormat = "ESRI Shapefile";
809 91 : const char *pszDataSource = NULL;
810 91 : const char *pszDestDataSource = NULL;
811 91 : char **papszLayers = NULL;
812 91 : char **papszDSCO = NULL, **papszLCO = NULL;
813 91 : int bTransform = FALSE;
814 91 : int bAppend = FALSE, bUpdate = FALSE, bOverwrite = FALSE;
815 91 : const char *pszOutputSRSDef = NULL;
816 91 : const char *pszSourceSRSDef = NULL;
817 91 : OGRSpatialReference *poOutputSRS = NULL;
818 91 : int bNullifyOutputSRS = FALSE;
819 91 : OGRSpatialReference *poSourceSRS = NULL;
820 91 : char *pszNewLayerName = NULL;
821 91 : const char *pszWHERE = NULL;
822 91 : OGRGeometry *poSpatialFilter = NULL;
823 : const char *pszSelect;
824 91 : char **papszSelFields = NULL;
825 91 : const char *pszSQLStatement = NULL;
826 91 : const char *pszDialect = NULL;
827 91 : int eGType = -2;
828 91 : int bPromoteToMulti = FALSE;
829 91 : GeomOperation eGeomOp = NONE;
830 91 : double dfGeomOpParam = 0;
831 91 : char **papszFieldTypesToString = NULL;
832 91 : int bDisplayProgress = FALSE;
833 91 : GDALProgressFunc pfnProgress = NULL;
834 91 : void *pProgressArg = NULL;
835 91 : int bWrapDateline = FALSE;
836 91 : const char *pszDateLineOffset = "10";
837 91 : int bClipSrc = FALSE;
838 91 : OGRGeometry* poClipSrc = NULL;
839 91 : const char *pszClipSrcDS = NULL;
840 91 : const char *pszClipSrcSQL = NULL;
841 91 : const char *pszClipSrcLayer = NULL;
842 91 : const char *pszClipSrcWhere = NULL;
843 91 : OGRGeometry *poClipDst = NULL;
844 91 : const char *pszClipDstDS = NULL;
845 91 : const char *pszClipDstSQL = NULL;
846 91 : const char *pszClipDstLayer = NULL;
847 91 : const char *pszClipDstWhere = NULL;
848 91 : int bSplitListFields = FALSE;
849 91 : int nMaxSplitListSubFields = -1;
850 91 : int bExplodeCollections = FALSE;
851 91 : const char *pszZField = NULL;
852 91 : const char *pszFieldMap = NULL;
853 91 : char **papszFieldMap = NULL;
854 91 : int nCoordDim = -1;
855 :
856 91 : int nGCPCount = 0;
857 91 : GDAL_GCP *pasGCPs = NULL;
858 91 : int nTransformOrder = 0; /* Default to 0 for now... let the lib decide */
859 :
860 : /* Check strict compilation and runtime library version as we use C++ API */
861 91 : if (! GDAL_CHECK_VERSION(papszArgv[0]))
862 0 : exit(1);
863 :
864 91 : EarlySetConfigOptions(nArgc, papszArgv);
865 :
866 : /* -------------------------------------------------------------------- */
867 : /* Register format(s). */
868 : /* -------------------------------------------------------------------- */
869 91 : OGRRegisterAll();
870 :
871 : /* -------------------------------------------------------------------- */
872 : /* Processing command line arguments. */
873 : /* -------------------------------------------------------------------- */
874 91 : nArgc = OGRGeneralCmdLineProcessor( nArgc, &papszArgv, 0 );
875 :
876 91 : if( nArgc < 1 )
877 0 : exit( -nArgc );
878 :
879 444 : for( int iArg = 1; iArg < nArgc; iArg++ )
880 : {
881 355 : if( EQUAL(papszArgv[iArg], "--utility_version") )
882 : {
883 : printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
884 2 : papszArgv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
885 2 : return 0;
886 : }
887 353 : else if( EQUAL(papszArgv[iArg],"--help") )
888 0 : Usage();
889 353 : else if ( EQUAL(papszArgv[iArg], "--long-usage") )
890 : {
891 0 : Usage(FALSE);
892 : }
893 :
894 353 : else if( EQUAL(papszArgv[iArg],"-q") || EQUAL(papszArgv[iArg],"-quiet") )
895 : {
896 0 : bQuiet = TRUE;
897 : }
898 353 : else if( EQUAL(papszArgv[iArg],"-f") )
899 : {
900 34 : CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
901 34 : bFormatExplicitelySet = TRUE;
902 34 : pszFormat = papszArgv[++iArg];
903 : }
904 319 : else if( EQUAL(papszArgv[iArg],"-dsco") )
905 : {
906 3 : CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
907 3 : papszDSCO = CSLAddString(papszDSCO, papszArgv[++iArg] );
908 : }
909 316 : else if( EQUAL(papszArgv[iArg],"-lco") )
910 : {
911 1 : CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
912 1 : papszLCO = CSLAddString(papszLCO, papszArgv[++iArg] );
913 : }
914 315 : else if( EQUAL(papszArgv[iArg],"-preserve_fid") )
915 : {
916 0 : bPreserveFID = TRUE;
917 : }
918 315 : else if( EQUALN(papszArgv[iArg],"-skip",5) )
919 : {
920 0 : bSkipFailures = TRUE;
921 0 : nGroupTransactions = 1; /* #2409 */
922 : }
923 315 : else if( EQUAL(papszArgv[iArg],"-append") )
924 : {
925 8 : bAppend = TRUE;
926 8 : bUpdate = TRUE;
927 : }
928 307 : else if( EQUAL(papszArgv[iArg],"-overwrite") )
929 : {
930 11 : bOverwrite = TRUE;
931 11 : bUpdate = TRUE;
932 : }
933 296 : else if( EQUAL(papszArgv[iArg],"-update") )
934 : {
935 4 : bUpdate = TRUE;
936 : }
937 292 : else if( EQUAL(papszArgv[iArg],"-fid") )
938 : {
939 1 : CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
940 1 : nFIDToFetch = atoi(papszArgv[++iArg]);
941 : }
942 291 : else if( EQUAL(papszArgv[iArg],"-sql") )
943 : {
944 7 : CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
945 7 : pszSQLStatement = papszArgv[++iArg];
946 : }
947 284 : else if( EQUAL(papszArgv[iArg],"-dialect") )
948 : {
949 0 : CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
950 0 : pszDialect = papszArgv[++iArg];
951 : }
952 284 : else if( EQUAL(papszArgv[iArg],"-nln") )
953 : {
954 13 : CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
955 13 : pszNewLayerName = CPLStrdup(papszArgv[++iArg]);
956 : }
957 271 : else if( EQUAL(papszArgv[iArg],"-nlt") )
958 : {
959 9 : CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
960 9 : int bIs3D = FALSE;
961 9 : CPLString osGeomName = papszArgv[iArg+1];
962 27 : if (strlen(papszArgv[iArg+1]) > 3 &&
963 18 : EQUALN(papszArgv[iArg+1] + strlen(papszArgv[iArg+1]) - 3, "25D", 3))
964 : {
965 1 : bIs3D = TRUE;
966 1 : osGeomName.resize(osGeomName.size() - 3);
967 : }
968 9 : if( EQUAL(osGeomName,"NONE") )
969 0 : eGType = wkbNone;
970 9 : else if( EQUAL(osGeomName,"GEOMETRY") )
971 0 : eGType = wkbUnknown;
972 9 : else if( EQUAL(osGeomName,"PROMOTE_TO_MULTI") )
973 2 : bPromoteToMulti = TRUE;
974 : else
975 : {
976 7 : eGType = OGRFromOGCGeomType(osGeomName);
977 7 : if (eGType == wkbUnknown)
978 : {
979 : fprintf( stderr, "-nlt %s: type not recognised.\n",
980 0 : papszArgv[iArg+1] );
981 0 : exit( 1 );
982 : }
983 : }
984 9 : if (eGType != -2 && eGType != wkbNone && bIs3D)
985 1 : eGType |= wkb25DBit;
986 :
987 9 : iArg++;
988 : }
989 262 : else if( EQUAL(papszArgv[iArg],"-dim") )
990 : {
991 2 : CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
992 2 : nCoordDim = atoi(papszArgv[iArg+1]);
993 2 : if( nCoordDim != 2 && nCoordDim != 3 )
994 : {
995 : fprintf( stderr, "-dim %s: value not handled.\n",
996 0 : papszArgv[iArg+1] );
997 0 : exit( 1 );
998 : }
999 2 : iArg ++;
1000 : }
1001 521 : else if( EQUAL(papszArgv[iArg],"-tg") ||
1002 260 : EQUAL(papszArgv[iArg],"-gt") )
1003 : {
1004 1 : CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
1005 1 : nGroupTransactions = atoi(papszArgv[++iArg]);
1006 : }
1007 259 : else if( EQUAL(papszArgv[iArg],"-s_srs") )
1008 : {
1009 1 : CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
1010 1 : pszSourceSRSDef = papszArgv[++iArg];
1011 : }
1012 258 : else if( EQUAL(papszArgv[iArg],"-a_srs") )
1013 : {
1014 3 : CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
1015 3 : pszOutputSRSDef = papszArgv[++iArg];
1016 3 : if (EQUAL(pszOutputSRSDef, "NULL") ||
1017 : EQUAL(pszOutputSRSDef, "NONE"))
1018 : {
1019 1 : pszOutputSRSDef = NULL;
1020 1 : bNullifyOutputSRS = TRUE;
1021 : }
1022 : }
1023 255 : else if( EQUAL(papszArgv[iArg],"-t_srs") )
1024 : {
1025 4 : CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
1026 4 : pszOutputSRSDef = papszArgv[++iArg];
1027 4 : bTransform = TRUE;
1028 : }
1029 251 : else if( EQUAL(papszArgv[iArg],"-spat") )
1030 : {
1031 2 : CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(4);
1032 2 : OGRLinearRing oRing;
1033 :
1034 2 : oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+2]) );
1035 2 : oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+4]) );
1036 2 : oRing.addPoint( atof(papszArgv[iArg+3]), atof(papszArgv[iArg+4]) );
1037 2 : oRing.addPoint( atof(papszArgv[iArg+3]), atof(papszArgv[iArg+2]) );
1038 2 : oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+2]) );
1039 :
1040 2 : poSpatialFilter = OGRGeometryFactory::createGeometry(wkbPolygon);
1041 2 : ((OGRPolygon *) poSpatialFilter)->addRing( &oRing );
1042 2 : iArg += 4;
1043 : }
1044 249 : else if( EQUAL(papszArgv[iArg],"-where") )
1045 : {
1046 3 : CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
1047 3 : pszWHERE = papszArgv[++iArg];
1048 : }
1049 246 : else if( EQUAL(papszArgv[iArg],"-select") )
1050 : {
1051 7 : CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
1052 7 : pszSelect = papszArgv[++iArg];
1053 : papszSelFields = CSLTokenizeStringComplex(pszSelect, " ,",
1054 7 : FALSE, FALSE );
1055 : }
1056 239 : else if( EQUAL(papszArgv[iArg],"-segmentize") )
1057 : {
1058 1 : CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
1059 1 : eGeomOp = SEGMENTIZE;
1060 1 : dfGeomOpParam = atof(papszArgv[++iArg]);
1061 : }
1062 238 : else if( EQUAL(papszArgv[iArg],"-simplify") )
1063 : {
1064 0 : CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
1065 0 : eGeomOp = SIMPLIFY_PRESERVE_TOPOLOGY;
1066 0 : dfGeomOpParam = atof(papszArgv[++iArg]);
1067 : }
1068 238 : else if( EQUAL(papszArgv[iArg],"-fieldTypeToString") )
1069 : {
1070 0 : CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
1071 : papszFieldTypesToString =
1072 0 : CSLTokenizeStringComplex(papszArgv[++iArg], " ,",
1073 0 : FALSE, FALSE );
1074 0 : char** iter = papszFieldTypesToString;
1075 0 : while(*iter)
1076 : {
1077 0 : if (EQUAL(*iter, "Integer") ||
1078 : EQUAL(*iter, "Real") ||
1079 : EQUAL(*iter, "String") ||
1080 : EQUAL(*iter, "Date") ||
1081 : EQUAL(*iter, "Time") ||
1082 : EQUAL(*iter, "DateTime") ||
1083 : EQUAL(*iter, "Binary") ||
1084 : EQUAL(*iter, "IntegerList") ||
1085 : EQUAL(*iter, "RealList") ||
1086 : EQUAL(*iter, "StringList"))
1087 : {
1088 : /* Do nothing */
1089 : }
1090 0 : else if (EQUAL(*iter, "All"))
1091 : {
1092 0 : CSLDestroy(papszFieldTypesToString);
1093 0 : papszFieldTypesToString = NULL;
1094 0 : papszFieldTypesToString = CSLAddString(papszFieldTypesToString, "All");
1095 0 : break;
1096 : }
1097 : else
1098 : {
1099 : Usage(CPLSPrintf("Unhandled type for fieldtypeasstring option : %s",
1100 0 : *iter));
1101 : }
1102 0 : iter ++;
1103 : }
1104 : }
1105 238 : else if( EQUAL(papszArgv[iArg],"-progress") )
1106 : {
1107 5 : bDisplayProgress = TRUE;
1108 : }
1109 233 : else if( EQUAL(papszArgv[iArg],"-wrapdateline") )
1110 : {
1111 4 : bWrapDateline = TRUE;
1112 : }
1113 229 : else if( EQUAL(papszArgv[iArg],"-datelineoffset") && iArg < nArgc-1 )
1114 : {
1115 0 : pszDateLineOffset = papszArgv[++iArg];
1116 : }
1117 229 : else if( EQUAL(papszArgv[iArg],"-clipsrc") )
1118 : {
1119 3 : if (iArg + 1 >= nArgc)
1120 0 : Usage(CPLSPrintf("%s option requires 1 or 4 arguments", papszArgv[iArg]));
1121 :
1122 : VSIStatBufL sStat;
1123 3 : bClipSrc = TRUE;
1124 3 : if ( IsNumber(papszArgv[iArg+1])
1125 0 : && papszArgv[iArg+2] != NULL
1126 0 : && papszArgv[iArg+3] != NULL
1127 0 : && papszArgv[iArg+4] != NULL)
1128 : {
1129 0 : OGRLinearRing oRing;
1130 :
1131 0 : oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+2]) );
1132 0 : oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+4]) );
1133 0 : oRing.addPoint( atof(papszArgv[iArg+3]), atof(papszArgv[iArg+4]) );
1134 0 : oRing.addPoint( atof(papszArgv[iArg+3]), atof(papszArgv[iArg+2]) );
1135 0 : oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+2]) );
1136 :
1137 0 : poClipSrc = OGRGeometryFactory::createGeometry(wkbPolygon);
1138 0 : ((OGRPolygon *) poClipSrc)->addRing( &oRing );
1139 0 : iArg += 4;
1140 : }
1141 6 : else if ((EQUALN(papszArgv[iArg+1], "POLYGON", 7) ||
1142 2 : EQUALN(papszArgv[iArg+1], "MULTIPOLYGON", 12)) &&
1143 1 : VSIStatL(papszArgv[iArg+1], &sStat) != 0)
1144 : {
1145 1 : char* pszTmp = (char*) papszArgv[iArg+1];
1146 1 : OGRGeometryFactory::createFromWkt(&pszTmp, NULL, &poClipSrc);
1147 1 : if (poClipSrc == NULL)
1148 : {
1149 0 : Usage("Invalid geometry. Must be a valid POLYGON or MULTIPOLYGON WKT");
1150 : }
1151 1 : iArg ++;
1152 : }
1153 2 : else if (EQUAL(papszArgv[iArg+1], "spat_extent") )
1154 : {
1155 1 : iArg ++;
1156 : }
1157 : else
1158 : {
1159 1 : pszClipSrcDS = papszArgv[iArg+1];
1160 1 : iArg ++;
1161 : }
1162 : }
1163 226 : else if( EQUAL(papszArgv[iArg],"-clipsrcsql") )
1164 : {
1165 0 : CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
1166 0 : pszClipSrcSQL = papszArgv[iArg+1];
1167 0 : iArg ++;
1168 : }
1169 226 : else if( EQUAL(papszArgv[iArg],"-clipsrclayer") )
1170 : {
1171 0 : CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
1172 0 : pszClipSrcLayer = papszArgv[iArg+1];
1173 0 : iArg ++;
1174 : }
1175 226 : else if( EQUAL(papszArgv[iArg],"-clipsrcwhere") )
1176 : {
1177 1 : CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
1178 1 : pszClipSrcWhere = papszArgv[iArg+1];
1179 1 : iArg ++;
1180 : }
1181 225 : else if( EQUAL(papszArgv[iArg],"-clipdst") )
1182 : {
1183 2 : if (iArg + 1 >= nArgc)
1184 0 : Usage(CPLSPrintf("%s option requires 1 or 4 arguments", papszArgv[iArg]));
1185 :
1186 : VSIStatBufL sStat;
1187 2 : if ( IsNumber(papszArgv[iArg+1])
1188 0 : && papszArgv[iArg+2] != NULL
1189 0 : && papszArgv[iArg+3] != NULL
1190 0 : && papszArgv[iArg+4] != NULL)
1191 : {
1192 0 : OGRLinearRing oRing;
1193 :
1194 0 : oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+2]) );
1195 0 : oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+4]) );
1196 0 : oRing.addPoint( atof(papszArgv[iArg+3]), atof(papszArgv[iArg+4]) );
1197 0 : oRing.addPoint( atof(papszArgv[iArg+3]), atof(papszArgv[iArg+2]) );
1198 0 : oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+2]) );
1199 :
1200 0 : poClipDst = OGRGeometryFactory::createGeometry(wkbPolygon);
1201 0 : ((OGRPolygon *) poClipDst)->addRing( &oRing );
1202 0 : iArg += 4;
1203 : }
1204 4 : else if ((EQUALN(papszArgv[iArg+1], "POLYGON", 7) ||
1205 1 : EQUALN(papszArgv[iArg+1], "MULTIPOLYGON", 12)) &&
1206 1 : VSIStatL(papszArgv[iArg+1], &sStat) != 0)
1207 : {
1208 1 : char* pszTmp = (char*) papszArgv[iArg+1];
1209 1 : OGRGeometryFactory::createFromWkt(&pszTmp, NULL, &poClipDst);
1210 1 : if (poClipDst == NULL)
1211 : {
1212 0 : Usage("Invalid geometry. Must be a valid POLYGON or MULTIPOLYGON WKT");
1213 : }
1214 1 : iArg ++;
1215 : }
1216 : else
1217 : {
1218 1 : pszClipDstDS = papszArgv[iArg+1];
1219 1 : iArg ++;
1220 : }
1221 : }
1222 223 : else if( EQUAL(papszArgv[iArg],"-clipdstsql") )
1223 : {
1224 1 : CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
1225 1 : pszClipDstSQL = papszArgv[iArg+1];
1226 1 : iArg ++;
1227 : }
1228 222 : else if( EQUAL(papszArgv[iArg],"-clipdstlayer") )
1229 : {
1230 0 : CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
1231 0 : pszClipDstLayer = papszArgv[iArg+1];
1232 0 : iArg ++;
1233 : }
1234 222 : else if( EQUAL(papszArgv[iArg],"-clipdstwhere") )
1235 : {
1236 0 : CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
1237 0 : pszClipDstWhere = papszArgv[iArg+1];
1238 0 : iArg ++;
1239 : }
1240 222 : else if( EQUAL(papszArgv[iArg],"-splitlistfields") )
1241 : {
1242 1 : bSplitListFields = TRUE;
1243 : }
1244 221 : else if ( EQUAL(papszArgv[iArg],"-maxsubfields") )
1245 : {
1246 0 : CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
1247 0 : if (IsNumber(papszArgv[iArg+1]))
1248 : {
1249 0 : int nTemp = atoi(papszArgv[iArg+1]);
1250 0 : if (nTemp > 0)
1251 : {
1252 0 : nMaxSplitListSubFields = nTemp;
1253 0 : iArg ++;
1254 : }
1255 : }
1256 : }
1257 221 : else if( EQUAL(papszArgv[iArg],"-explodecollections") )
1258 : {
1259 1 : bExplodeCollections = TRUE;
1260 : }
1261 220 : else if( EQUAL(papszArgv[iArg],"-zfield") )
1262 : {
1263 3 : CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
1264 3 : pszZField = papszArgv[iArg+1];
1265 3 : iArg ++;
1266 : }
1267 217 : else if( EQUAL(papszArgv[iArg],"-gcp") )
1268 : {
1269 15 : CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(4);
1270 15 : char* endptr = NULL;
1271 : /* -gcp pixel line easting northing [elev] */
1272 :
1273 15 : nGCPCount++;
1274 : pasGCPs = (GDAL_GCP *)
1275 15 : CPLRealloc( pasGCPs, sizeof(GDAL_GCP) * nGCPCount );
1276 15 : GDALInitGCPs( 1, pasGCPs + nGCPCount - 1 );
1277 :
1278 15 : pasGCPs[nGCPCount-1].dfGCPPixel = atof(papszArgv[++iArg]);
1279 15 : pasGCPs[nGCPCount-1].dfGCPLine = atof(papszArgv[++iArg]);
1280 15 : pasGCPs[nGCPCount-1].dfGCPX = atof(papszArgv[++iArg]);
1281 15 : pasGCPs[nGCPCount-1].dfGCPY = atof(papszArgv[++iArg]);
1282 43 : if( papszArgv[iArg+1] != NULL
1283 28 : && (CPLStrtod(papszArgv[iArg+1], &endptr) != 0.0 || papszArgv[iArg+1][0] == '0') )
1284 : {
1285 : /* Check that last argument is really a number and not a filename */
1286 : /* looking like a number (see ticket #863) */
1287 0 : if (endptr && *endptr == 0)
1288 0 : pasGCPs[nGCPCount-1].dfGCPZ = atof(papszArgv[++iArg]);
1289 : }
1290 :
1291 : /* should set id and info? */
1292 : }
1293 202 : else if( EQUAL(papszArgv[iArg],"-tps") )
1294 : {
1295 1 : nTransformOrder = -1;
1296 : }
1297 201 : else if( EQUAL(papszArgv[iArg],"-order") )
1298 : {
1299 1 : CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
1300 1 : nTransformOrder = atoi( papszArgv[++iArg] );
1301 : }
1302 202 : else if( EQUAL(papszArgv[iArg],"-fieldmap") && papszArgv[iArg+1] != NULL)
1303 : {
1304 2 : CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
1305 2 : pszFieldMap = papszArgv[++iArg];
1306 : papszFieldMap = CSLTokenizeStringComplex(pszFieldMap, ",",
1307 2 : FALSE, FALSE );
1308 : }
1309 198 : else if( papszArgv[iArg][0] == '-' )
1310 : {
1311 0 : Usage(CPLSPrintf("Unkown option name '%s'", papszArgv[iArg]));
1312 : }
1313 198 : else if( pszDestDataSource == NULL )
1314 89 : pszDestDataSource = papszArgv[iArg];
1315 109 : else if( pszDataSource == NULL )
1316 89 : pszDataSource = papszArgv[iArg];
1317 : else
1318 20 : papszLayers = CSLAddString( papszLayers, papszArgv[iArg] );
1319 : }
1320 :
1321 89 : if( pszDataSource == NULL )
1322 : {
1323 0 : if( pszDestDataSource == NULL )
1324 0 : Usage("no target datasource provided");
1325 : else
1326 0 : Usage("no source datasource provided");
1327 : }
1328 :
1329 89 : if( bPreserveFID && bExplodeCollections )
1330 : {
1331 0 : Usage("cannot use -preserve_fid and -explodecollections at the same time.");
1332 : }
1333 :
1334 89 : if (pszFieldMap && !bAppend)
1335 : {
1336 0 : Usage("if -fieldmap is specified, -append must also be specified");
1337 : }
1338 :
1339 90 : if( bClipSrc && pszClipSrcDS != NULL)
1340 : {
1341 1 : poClipSrc = LoadGeometry(pszClipSrcDS, pszClipSrcSQL, pszClipSrcLayer, pszClipSrcWhere);
1342 1 : if (poClipSrc == NULL)
1343 : {
1344 0 : Usage("cannot load source clip geometry");
1345 : }
1346 : }
1347 88 : else if( bClipSrc && poClipSrc == NULL )
1348 : {
1349 1 : if (poSpatialFilter)
1350 1 : poClipSrc = poSpatialFilter->clone();
1351 1 : if (poClipSrc == NULL)
1352 : {
1353 : Usage("-clipsrc must be used with -spat option or a\n"
1354 0 : "bounding box, WKT string or datasource must be specified");
1355 : }
1356 : }
1357 :
1358 89 : if( pszClipDstDS != NULL)
1359 : {
1360 1 : poClipDst = LoadGeometry(pszClipDstDS, pszClipDstSQL, pszClipDstLayer, pszClipDstWhere);
1361 1 : if (poClipDst == NULL)
1362 : {
1363 0 : Usage("cannot load dest clip geometry");
1364 : }
1365 : }
1366 :
1367 : /* -------------------------------------------------------------------- */
1368 : /* Open data source. */
1369 : /* -------------------------------------------------------------------- */
1370 : OGRDataSource *poDS;
1371 89 : OGRDataSource *poODS = NULL;
1372 89 : OGRSFDriver *poDriver = NULL;
1373 89 : int bCloseODS = TRUE;
1374 :
1375 : /* Avoid opening twice the same datasource if it is both the input and output */
1376 : /* Known to cause problems with at least FGdb and SQlite drivers. See #4270 */
1377 92 : if (bUpdate && strcmp(pszDestDataSource, pszDataSource) == 0)
1378 : {
1379 3 : poODS = poDS = OGRSFDriverRegistrar::Open( pszDataSource, TRUE, &poDriver );
1380 : /* Restrict to those 2 drivers. For example it is known to break with */
1381 : /* the PG driver due to the way it manages transactions... */
1382 6 : if (poDS && !(EQUAL(poDriver->GetName(), "FileGDB") ||
1383 3 : EQUAL(poDriver->GetName(), "SQLite")))
1384 : {
1385 2 : poDS = OGRSFDriverRegistrar::Open( pszDataSource, FALSE );
1386 : }
1387 : else
1388 1 : bCloseODS = FALSE;
1389 3 : if (poDS)
1390 : {
1391 3 : if (bOverwrite || bAppend)
1392 : {
1393 : /* Various tests to avoid overwriting the source layer(s) */
1394 : /* or to avoid appending a layer to itself */
1395 1 : int bError = FALSE;
1396 1 : if (pszNewLayerName == NULL)
1397 0 : bError = TRUE;
1398 1 : else if (CSLCount(papszLayers) == 1)
1399 1 : bError = strcmp(pszNewLayerName, papszLayers[0]) == 0;
1400 0 : else if (pszSQLStatement == NULL)
1401 0 : bError = TRUE;
1402 1 : if (bError)
1403 : {
1404 : fprintf( stderr,
1405 : "ERROR: -nln name must be specified combined with "
1406 : "a single source layer name,\nor a -sql statement, and "
1407 0 : "name must be different from an existing layer.\n");
1408 0 : exit(1);
1409 : }
1410 : }
1411 : }
1412 : }
1413 : else
1414 86 : poDS = OGRSFDriverRegistrar::Open( pszDataSource, FALSE );
1415 :
1416 : /* -------------------------------------------------------------------- */
1417 : /* Report failure */
1418 : /* -------------------------------------------------------------------- */
1419 89 : if( poDS == NULL )
1420 : {
1421 0 : OGRSFDriverRegistrar *poR = OGRSFDriverRegistrar::GetRegistrar();
1422 :
1423 : fprintf( stderr, "FAILURE:\n"
1424 : "Unable to open datasource `%s' with the following drivers.\n",
1425 0 : pszDataSource );
1426 :
1427 0 : for( int iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
1428 : {
1429 0 : fprintf( stderr, " -> %s\n", poR->GetDriver(iDriver)->GetName() );
1430 : }
1431 :
1432 0 : exit( 1 );
1433 : }
1434 :
1435 : /* -------------------------------------------------------------------- */
1436 : /* Try opening the output datasource as an existing, writable */
1437 : /* -------------------------------------------------------------------- */
1438 :
1439 89 : if( bUpdate && poODS == NULL )
1440 : {
1441 18 : poODS = OGRSFDriverRegistrar::Open( pszDestDataSource, TRUE, &poDriver );
1442 :
1443 18 : if( poODS == NULL )
1444 : {
1445 1 : if (bOverwrite || bAppend)
1446 : {
1447 1 : poODS = OGRSFDriverRegistrar::Open( pszDestDataSource, FALSE, &poDriver );
1448 1 : if (poODS == NULL)
1449 : {
1450 : /* ok the datasource doesn't exist at all */
1451 1 : bUpdate = FALSE;
1452 : }
1453 : else
1454 : {
1455 0 : OGRDataSource::DestroyDataSource(poODS);
1456 0 : poODS = NULL;
1457 : }
1458 : }
1459 :
1460 1 : if (bUpdate)
1461 : {
1462 : fprintf( stderr, "FAILURE:\n"
1463 : "Unable to open existing output datasource `%s'.\n",
1464 0 : pszDestDataSource );
1465 0 : exit( 1 );
1466 : }
1467 : }
1468 17 : else if( CSLCount(papszDSCO) > 0 )
1469 : {
1470 : fprintf( stderr, "WARNING: Datasource creation options ignored since an existing datasource\n"
1471 0 : " being updated.\n" );
1472 : }
1473 : }
1474 :
1475 : /* -------------------------------------------------------------------- */
1476 : /* Find the output driver. */
1477 : /* -------------------------------------------------------------------- */
1478 89 : if( !bUpdate )
1479 : {
1480 69 : if (!bQuiet && !bFormatExplicitelySet)
1481 43 : CheckDestDataSourceNameConsistency(pszDestDataSource, pszFormat);
1482 :
1483 69 : OGRSFDriverRegistrar *poR = OGRSFDriverRegistrar::GetRegistrar();
1484 : int iDriver;
1485 :
1486 69 : poDriver = poR->GetDriverByName(pszFormat);
1487 69 : if( poDriver == NULL )
1488 : {
1489 0 : fprintf( stderr, "Unable to find driver `%s'.\n", pszFormat );
1490 0 : fprintf( stderr, "The following drivers are available:\n" );
1491 :
1492 0 : for( iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
1493 : {
1494 0 : fprintf( stderr, " -> `%s'\n", poR->GetDriver(iDriver)->GetName() );
1495 : }
1496 0 : exit( 1 );
1497 : }
1498 :
1499 69 : if( !poDriver->TestCapability( ODrCCreateDataSource ) )
1500 : {
1501 : fprintf( stderr, "%s driver does not support data source creation.\n",
1502 0 : pszFormat );
1503 0 : exit( 1 );
1504 : }
1505 :
1506 : /* -------------------------------------------------------------------- */
1507 : /* Special case to improve user experience when translating */
1508 : /* a datasource with multiple layers into a shapefile. If the */
1509 : /* user gives a target datasource with .shp and it does not exist, */
1510 : /* the shapefile driver will try to create a file, but this is not */
1511 : /* appropriate because here we have several layers, so create */
1512 : /* a directory instead. */
1513 : /* -------------------------------------------------------------------- */
1514 : VSIStatBufL sStat;
1515 104 : if (EQUAL(poDriver->GetName(), "ESRI Shapefile") &&
1516 : pszSQLStatement == NULL &&
1517 : (CSLCount(papszLayers) > 1 ||
1518 35 : (CSLCount(papszLayers) == 0 && poDS->GetLayerCount() > 1)) &&
1519 : pszNewLayerName == NULL &&
1520 : EQUAL(CPLGetExtension(pszDestDataSource), "SHP") &&
1521 : VSIStatL(pszDestDataSource, &sStat) != 0)
1522 : {
1523 1 : if (VSIMkdir(pszDestDataSource, 0755) != 0)
1524 : {
1525 : CPLError( CE_Failure, CPLE_AppDefined,
1526 : "Failed to create directory %s\n"
1527 : "for shapefile datastore.\n",
1528 0 : pszDestDataSource );
1529 0 : exit(1);
1530 : }
1531 : }
1532 :
1533 : /* -------------------------------------------------------------------- */
1534 : /* Create the output data source. */
1535 : /* -------------------------------------------------------------------- */
1536 69 : poODS = poDriver->CreateDataSource( pszDestDataSource, papszDSCO );
1537 69 : if( poODS == NULL )
1538 : {
1539 : fprintf( stderr, "%s driver failed to create %s\n",
1540 0 : pszFormat, pszDestDataSource );
1541 0 : exit( 1 );
1542 : }
1543 : }
1544 :
1545 : /* -------------------------------------------------------------------- */
1546 : /* Parse the output SRS definition if possible. */
1547 : /* -------------------------------------------------------------------- */
1548 89 : if( pszOutputSRSDef != NULL )
1549 : {
1550 6 : poOutputSRS = (OGRSpatialReference*)OSRNewSpatialReference(NULL);
1551 6 : if( poOutputSRS->SetFromUserInput( pszOutputSRSDef ) != OGRERR_NONE )
1552 : {
1553 : fprintf( stderr, "Failed to process SRS definition: %s\n",
1554 0 : pszOutputSRSDef );
1555 0 : exit( 1 );
1556 : }
1557 : }
1558 :
1559 : /* -------------------------------------------------------------------- */
1560 : /* Parse the source SRS definition if possible. */
1561 : /* -------------------------------------------------------------------- */
1562 89 : if( pszSourceSRSDef != NULL )
1563 : {
1564 1 : poSourceSRS = (OGRSpatialReference*)OSRNewSpatialReference(NULL);
1565 1 : if( poSourceSRS->SetFromUserInput( pszSourceSRSDef ) != OGRERR_NONE )
1566 : {
1567 : fprintf( stderr, "Failed to process SRS definition: %s\n",
1568 0 : pszSourceSRSDef );
1569 0 : exit( 1 );
1570 : }
1571 : }
1572 :
1573 : /* -------------------------------------------------------------------- */
1574 : /* Create a transformation object from the source to */
1575 : /* destination coordinate system. */
1576 : /* -------------------------------------------------------------------- */
1577 89 : GCPCoordTransformation *poGCPCoordTrans = NULL;
1578 89 : if( nGCPCount > 0 )
1579 : {
1580 : poGCPCoordTrans = new GCPCoordTransformation( nGCPCount, pasGCPs,
1581 : nTransformOrder,
1582 5 : poSourceSRS ? poSourceSRS : poOutputSRS );
1583 5 : if( !(poGCPCoordTrans->IsValid()) )
1584 : {
1585 0 : delete poGCPCoordTrans;
1586 0 : poGCPCoordTrans = NULL;
1587 : }
1588 : }
1589 :
1590 : /* -------------------------------------------------------------------- */
1591 : /* For OSM file. */
1592 : /* -------------------------------------------------------------------- */
1593 : int bSrcIsOSM = (poDS->GetDriver() != NULL &&
1594 89 : strcmp(poDS->GetDriver()->GetName(), "OSM") == 0);
1595 89 : vsi_l_offset nSrcFileSize = 0;
1596 89 : if( bSrcIsOSM && strcmp(poDS->GetName(), "/vsistdin/") != 0)
1597 : {
1598 : VSIStatBufL sStat;
1599 4 : if( VSIStatL(poDS->GetName(), &sStat) == 0 )
1600 4 : nSrcFileSize = sStat.st_size;
1601 : }
1602 :
1603 : /* -------------------------------------------------------------------- */
1604 : /* Special case for -sql clause. No source layers required. */
1605 : /* -------------------------------------------------------------------- */
1606 89 : if( pszSQLStatement != NULL )
1607 : {
1608 : OGRLayer *poResultSet;
1609 :
1610 7 : if( pszWHERE != NULL )
1611 0 : fprintf( stderr, "-where clause ignored in combination with -sql.\n" );
1612 7 : if( CSLCount(papszLayers) > 0 )
1613 0 : fprintf( stderr, "layer names ignored in combination with -sql.\n" );
1614 :
1615 : poResultSet = poDS->ExecuteSQL( pszSQLStatement, poSpatialFilter,
1616 7 : pszDialect );
1617 :
1618 7 : if( poResultSet != NULL )
1619 : {
1620 7 : long nCountLayerFeatures = 0;
1621 7 : if (bDisplayProgress)
1622 : {
1623 1 : if (bSrcIsOSM)
1624 : {
1625 1 : pfnProgress = GDALTermProgress;
1626 : }
1627 0 : else if (!poResultSet->TestCapability(OLCFastFeatureCount))
1628 : {
1629 0 : fprintf( stderr, "Progress turned off as fast feature count is not available.\n");
1630 0 : bDisplayProgress = FALSE;
1631 : }
1632 : else
1633 : {
1634 0 : nCountLayerFeatures = poResultSet->GetFeatureCount();
1635 0 : pfnProgress = GDALTermProgress;
1636 : }
1637 : }
1638 :
1639 7 : OGRLayer* poPassedLayer = poResultSet;
1640 7 : if (bSplitListFields)
1641 : {
1642 0 : poPassedLayer = new OGRSplitListFieldLayer(poPassedLayer, nMaxSplitListSubFields);
1643 0 : int nRet = ((OGRSplitListFieldLayer*)poPassedLayer)->BuildLayerDefn(NULL, NULL);
1644 0 : if (!nRet)
1645 : {
1646 0 : delete poPassedLayer;
1647 0 : poPassedLayer = poResultSet;
1648 : }
1649 : }
1650 :
1651 : /* -------------------------------------------------------------------- */
1652 : /* Special case to improve user experience when translating into */
1653 : /* single file shapefile and source has only one layer, and that */
1654 : /* the layer name isn't specified */
1655 : /* -------------------------------------------------------------------- */
1656 : VSIStatBufL sStat;
1657 7 : if (EQUAL(poDriver->GetName(), "ESRI Shapefile") &&
1658 : pszNewLayerName == NULL &&
1659 : VSIStatL(pszDestDataSource, &sStat) == 0 && VSI_ISREG(sStat.st_mode))
1660 : {
1661 0 : pszNewLayerName = CPLStrdup(CPLGetBasename(pszDestDataSource));
1662 : }
1663 :
1664 : TargetLayerInfo* psInfo = SetupTargetLayer( poDS,
1665 : poPassedLayer,
1666 : poODS,
1667 : papszLCO,
1668 : pszNewLayerName,
1669 : poOutputSRS,
1670 : bNullifyOutputSRS,
1671 : papszSelFields,
1672 : bAppend, eGType,
1673 : bPromoteToMulti,
1674 : nCoordDim, bOverwrite,
1675 : papszFieldTypesToString,
1676 : bExplodeCollections,
1677 : pszZField,
1678 : papszFieldMap,
1679 7 : pszWHERE );
1680 :
1681 7 : poPassedLayer->ResetReading();
1682 :
1683 7 : if( psInfo == NULL ||
1684 : !TranslateLayer( psInfo, poDS, poPassedLayer, poODS,
1685 : bTransform, bWrapDateline, pszDateLineOffset,
1686 : poOutputSRS, bNullifyOutputSRS,
1687 : poSourceSRS,
1688 : poGCPCoordTrans,
1689 : eGType, bPromoteToMulti, nCoordDim,
1690 : eGeomOp, dfGeomOpParam,
1691 : nCountLayerFeatures,
1692 : poClipSrc, poClipDst,
1693 : bExplodeCollections,
1694 : nSrcFileSize, NULL,
1695 : pfnProgress, pProgressArg ))
1696 : {
1697 : CPLError( CE_Failure, CPLE_AppDefined,
1698 : "Terminating translation prematurely after failed\n"
1699 0 : "translation from sql statement." );
1700 :
1701 0 : exit( 1 );
1702 : }
1703 :
1704 7 : FreeTargetLayerInfo(psInfo);
1705 :
1706 7 : if (poPassedLayer != poResultSet)
1707 0 : delete poPassedLayer;
1708 :
1709 7 : poDS->ReleaseResultSet( poResultSet );
1710 : }
1711 : else
1712 : {
1713 0 : if( CPLGetLastErrorNo() != 0 )
1714 0 : nRetCode = 1;
1715 : }
1716 : }
1717 :
1718 : /* -------------------------------------------------------------------- */
1719 : /* Special case for layer interleaving mode. */
1720 : /* -------------------------------------------------------------------- */
1721 82 : else if( bSrcIsOSM &&
1722 : CSLTestBoolean(CPLGetConfigOption("OGR_INTERLEAVED_READING", "YES")) )
1723 : {
1724 3 : CPLSetConfigOption("OGR_INTERLEAVED_READING", "YES");
1725 :
1726 3 : if (bSplitListFields)
1727 : {
1728 0 : fprintf( stderr, "FAILURE: -splitlistfields not supported in this mode\n" );
1729 0 : exit( 1 );
1730 : }
1731 :
1732 3 : int nSrcLayerCount = poDS->GetLayerCount();
1733 : AssociatedLayers* pasAssocLayers =
1734 3 : (AssociatedLayers* ) CPLCalloc(nSrcLayerCount, sizeof(AssociatedLayers));
1735 :
1736 : /* -------------------------------------------------------------------- */
1737 : /* Special case to improve user experience when translating into */
1738 : /* single file shapefile and source has only one layer, and that */
1739 : /* the layer name isn't specified */
1740 : /* -------------------------------------------------------------------- */
1741 : VSIStatBufL sStat;
1742 3 : if (EQUAL(poDriver->GetName(), "ESRI Shapefile") &&
1743 : (CSLCount(papszLayers) == 1 || nSrcLayerCount == 1) && pszNewLayerName == NULL &&
1744 : VSIStatL(pszDestDataSource, &sStat) == 0 && VSI_ISREG(sStat.st_mode))
1745 : {
1746 0 : pszNewLayerName = CPLStrdup(CPLGetBasename(pszDestDataSource));
1747 : }
1748 :
1749 3 : if ( bDisplayProgress && bSrcIsOSM )
1750 3 : pfnProgress = GDALTermProgress;
1751 :
1752 : /* -------------------------------------------------------------------- */
1753 : /* If no target layer specified, use all source layers. */
1754 : /* -------------------------------------------------------------------- */
1755 : int iLayer;
1756 3 : if ( CSLCount(papszLayers) == 0)
1757 : {
1758 0 : papszLayers = (char**) CPLCalloc(sizeof(char*), nSrcLayerCount + 1);
1759 0 : for( iLayer = 0; iLayer < nSrcLayerCount; iLayer++ )
1760 : {
1761 0 : OGRLayer *poLayer = poDS->GetLayer(iLayer);
1762 :
1763 0 : if( poLayer == NULL )
1764 : {
1765 : fprintf( stderr, "FAILURE: Couldn't fetch advertised layer %d!\n",
1766 0 : iLayer );
1767 0 : exit( 1 );
1768 : }
1769 :
1770 0 : papszLayers[iLayer] = CPLStrdup(poLayer->GetName());
1771 : }
1772 : }
1773 : else
1774 : {
1775 3 : if ( bSrcIsOSM )
1776 : {
1777 3 : CPLString osInterestLayers = "SET interest_layers =";
1778 18 : for( iLayer = 0; papszLayers[iLayer] != NULL; iLayer++ )
1779 : {
1780 15 : if( iLayer != 0 ) osInterestLayers += ",";
1781 15 : osInterestLayers += papszLayers[iLayer];
1782 : }
1783 :
1784 3 : poDS->ExecuteSQL(osInterestLayers.c_str(), NULL, NULL);
1785 : }
1786 : }
1787 :
1788 : /* -------------------------------------------------------------------- */
1789 : /* First pass to set filters and create target layers. */
1790 : /* -------------------------------------------------------------------- */
1791 18 : for( iLayer = 0; iLayer < nSrcLayerCount; iLayer++ )
1792 : {
1793 15 : OGRLayer *poLayer = poDS->GetLayer(iLayer);
1794 15 : if( poLayer == NULL )
1795 : {
1796 : fprintf( stderr, "FAILURE: Couldn't fetch advertised layer %d!\n",
1797 0 : iLayer );
1798 0 : exit( 1 );
1799 : }
1800 :
1801 15 : pasAssocLayers[iLayer].poSrcLayer = poLayer;
1802 :
1803 15 : if( CSLFindString(papszLayers, poLayer->GetName()) >= 0 )
1804 : {
1805 12 : if( pszWHERE != NULL )
1806 : {
1807 0 : if( poLayer->SetAttributeFilter( pszWHERE ) != OGRERR_NONE )
1808 : {
1809 : fprintf( stderr, "FAILURE: SetAttributeFilter(%s) on layer '%s' failed.\n",
1810 0 : pszWHERE, poLayer->GetName() );
1811 0 : if (!bSkipFailures)
1812 0 : exit( 1 );
1813 : }
1814 : }
1815 :
1816 12 : if( poSpatialFilter != NULL )
1817 0 : poLayer->SetSpatialFilter( poSpatialFilter );
1818 :
1819 : TargetLayerInfo* psInfo = SetupTargetLayer( poDS,
1820 : poLayer,
1821 : poODS,
1822 : papszLCO,
1823 : pszNewLayerName,
1824 : poOutputSRS,
1825 : bNullifyOutputSRS,
1826 : papszSelFields,
1827 : bAppend, eGType,
1828 : bPromoteToMulti,
1829 : nCoordDim, bOverwrite,
1830 : papszFieldTypesToString,
1831 : bExplodeCollections,
1832 : pszZField,
1833 : papszFieldMap,
1834 12 : pszWHERE );
1835 :
1836 12 : if( psInfo == NULL && !bSkipFailures )
1837 0 : exit(1);
1838 :
1839 12 : pasAssocLayers[iLayer].psInfo = psInfo;
1840 : }
1841 : else
1842 : {
1843 3 : pasAssocLayers[iLayer].psInfo = NULL;
1844 : }
1845 : }
1846 :
1847 : /* -------------------------------------------------------------------- */
1848 : /* Second pass to process features in a interleaved layer mode. */
1849 : /* -------------------------------------------------------------------- */
1850 : int bHasLayersNonEmpty;
1851 6 : do
1852 : {
1853 6 : bHasLayersNonEmpty = FALSE;
1854 :
1855 36 : for( iLayer = 0; iLayer < nSrcLayerCount; iLayer++ )
1856 : {
1857 30 : OGRLayer *poLayer = pasAssocLayers[iLayer].poSrcLayer;
1858 30 : TargetLayerInfo *psInfo = pasAssocLayers[iLayer].psInfo;
1859 30 : GIntBig nReadFeatureCount = 0;
1860 :
1861 30 : if( psInfo )
1862 : {
1863 24 : if( !TranslateLayer(psInfo, poDS, poLayer, poODS,
1864 : bTransform, bWrapDateline, pszDateLineOffset,
1865 : poOutputSRS, bNullifyOutputSRS,
1866 : poSourceSRS,
1867 : poGCPCoordTrans,
1868 : eGType, bPromoteToMulti, nCoordDim,
1869 : eGeomOp, dfGeomOpParam,
1870 : 0,
1871 : poClipSrc, poClipDst,
1872 : bExplodeCollections,
1873 : nSrcFileSize,
1874 : &nReadFeatureCount,
1875 : pfnProgress, pProgressArg )
1876 : && !bSkipFailures )
1877 : {
1878 : CPLError( CE_Failure, CPLE_AppDefined,
1879 : "Terminating translation prematurely after failed\n"
1880 : "translation of layer %s (use -skipfailures to skip errors)\n",
1881 0 : poLayer->GetName() );
1882 :
1883 0 : exit( 1 );
1884 : }
1885 : }
1886 : else
1887 : {
1888 : /* No matching target layer : just consumes the features */
1889 :
1890 : OGRFeature* poFeature;
1891 12 : while( (poFeature = poLayer->GetNextFeature()) != NULL )
1892 : {
1893 0 : nReadFeatureCount ++;
1894 0 : OGRFeature::DestroyFeature(poFeature);
1895 : }
1896 : }
1897 :
1898 30 : if( nReadFeatureCount != 0 )
1899 12 : bHasLayersNonEmpty = TRUE;
1900 : }
1901 : }
1902 : while( bHasLayersNonEmpty );
1903 :
1904 : /* -------------------------------------------------------------------- */
1905 : /* Cleanup. */
1906 : /* -------------------------------------------------------------------- */
1907 18 : for( iLayer = 0; iLayer < nSrcLayerCount; iLayer++ )
1908 : {
1909 15 : if( pasAssocLayers[iLayer].psInfo )
1910 12 : FreeTargetLayerInfo(pasAssocLayers[iLayer].psInfo);
1911 : }
1912 3 : CPLFree(pasAssocLayers);
1913 : }
1914 :
1915 : else
1916 : {
1917 79 : int nLayerCount = 0;
1918 79 : OGRLayer** papoLayers = NULL;
1919 :
1920 : /* -------------------------------------------------------------------- */
1921 : /* Process each data source layer. */
1922 : /* -------------------------------------------------------------------- */
1923 79 : if ( CSLCount(papszLayers) == 0)
1924 : {
1925 74 : nLayerCount = poDS->GetLayerCount();
1926 74 : papoLayers = (OGRLayer**)CPLMalloc(sizeof(OGRLayer*) * nLayerCount);
1927 :
1928 180 : for( int iLayer = 0;
1929 : iLayer < nLayerCount;
1930 : iLayer++ )
1931 : {
1932 106 : OGRLayer *poLayer = poDS->GetLayer(iLayer);
1933 :
1934 106 : if( poLayer == NULL )
1935 : {
1936 : fprintf( stderr, "FAILURE: Couldn't fetch advertised layer %d!\n",
1937 0 : iLayer );
1938 0 : exit( 1 );
1939 : }
1940 :
1941 106 : papoLayers[iLayer] = poLayer;
1942 : }
1943 : }
1944 : /* -------------------------------------------------------------------- */
1945 : /* Process specified data source layers. */
1946 : /* -------------------------------------------------------------------- */
1947 : else
1948 : {
1949 5 : nLayerCount = CSLCount(papszLayers);
1950 5 : papoLayers = (OGRLayer**)CPLMalloc(sizeof(OGRLayer*) * nLayerCount);
1951 :
1952 20 : for( int iLayer = 0;
1953 10 : papszLayers[iLayer] != NULL;
1954 : iLayer++ )
1955 : {
1956 5 : OGRLayer *poLayer = poDS->GetLayerByName(papszLayers[iLayer]);
1957 :
1958 5 : if( poLayer == NULL )
1959 : {
1960 : fprintf( stderr, "FAILURE: Couldn't fetch requested layer '%s'!\n",
1961 0 : papszLayers[iLayer] );
1962 0 : if (!bSkipFailures)
1963 0 : exit( 1 );
1964 : }
1965 :
1966 5 : papoLayers[iLayer] = poLayer;
1967 : }
1968 : }
1969 :
1970 : /* -------------------------------------------------------------------- */
1971 : /* Special case to improve user experience when translating into */
1972 : /* single file shapefile and source has only one layer, and that */
1973 : /* the layer name isn't specified */
1974 : /* -------------------------------------------------------------------- */
1975 : VSIStatBufL sStat;
1976 79 : if (EQUAL(poDriver->GetName(), "ESRI Shapefile") &&
1977 : nLayerCount == 1 && pszNewLayerName == NULL &&
1978 : VSIStatL(pszDestDataSource, &sStat) == 0 && VSI_ISREG(sStat.st_mode))
1979 : {
1980 3 : pszNewLayerName = CPLStrdup(CPLGetBasename(pszDestDataSource));
1981 : }
1982 :
1983 79 : long* panLayerCountFeatures = (long*) CPLCalloc(sizeof(long), nLayerCount);
1984 79 : long nCountLayersFeatures = 0;
1985 79 : long nAccCountFeatures = 0;
1986 : int iLayer;
1987 :
1988 : /* First pass to apply filters and count all features if necessary */
1989 190 : for( iLayer = 0;
1990 : iLayer < nLayerCount;
1991 : iLayer++ )
1992 : {
1993 111 : OGRLayer *poLayer = papoLayers[iLayer];
1994 111 : if (poLayer == NULL)
1995 0 : continue;
1996 :
1997 111 : if( pszWHERE != NULL )
1998 : {
1999 3 : if( poLayer->SetAttributeFilter( pszWHERE ) != OGRERR_NONE )
2000 : {
2001 : fprintf( stderr, "FAILURE: SetAttributeFilter(%s) on layer '%s' failed.\n",
2002 0 : pszWHERE, poLayer->GetName() );
2003 0 : if (!bSkipFailures)
2004 0 : exit( 1 );
2005 : }
2006 : }
2007 :
2008 111 : if( poSpatialFilter != NULL )
2009 2 : poLayer->SetSpatialFilter( poSpatialFilter );
2010 :
2011 111 : if (bDisplayProgress && !bSrcIsOSM)
2012 : {
2013 1 : if (!poLayer->TestCapability(OLCFastFeatureCount))
2014 : {
2015 0 : fprintf( stderr, "Progress turned off as fast feature count is not available.\n");
2016 0 : bDisplayProgress = FALSE;
2017 : }
2018 : else
2019 : {
2020 1 : panLayerCountFeatures[iLayer] = poLayer->GetFeatureCount();
2021 1 : nCountLayersFeatures += panLayerCountFeatures[iLayer];
2022 : }
2023 : }
2024 : }
2025 :
2026 : /* Second pass to do the real job */
2027 190 : for( iLayer = 0;
2028 : iLayer < nLayerCount;
2029 : iLayer++ )
2030 : {
2031 111 : OGRLayer *poLayer = papoLayers[iLayer];
2032 111 : if (poLayer == NULL)
2033 0 : continue;
2034 :
2035 :
2036 111 : OGRLayer* poPassedLayer = poLayer;
2037 111 : if (bSplitListFields)
2038 : {
2039 1 : poPassedLayer = new OGRSplitListFieldLayer(poPassedLayer, nMaxSplitListSubFields);
2040 :
2041 1 : if (bDisplayProgress && nMaxSplitListSubFields != 1)
2042 : {
2043 0 : pfnProgress = GDALScaledProgress;
2044 : pProgressArg =
2045 : GDALCreateScaledProgress(nAccCountFeatures * 1.0 / nCountLayersFeatures,
2046 0 : (nAccCountFeatures + panLayerCountFeatures[iLayer] / 2) * 1.0 / nCountLayersFeatures,
2047 : GDALTermProgress,
2048 0 : NULL);
2049 : }
2050 : else
2051 : {
2052 1 : pfnProgress = NULL;
2053 1 : pProgressArg = NULL;
2054 : }
2055 :
2056 1 : int nRet = ((OGRSplitListFieldLayer*)poPassedLayer)->BuildLayerDefn(pfnProgress, pProgressArg);
2057 1 : if (!nRet)
2058 : {
2059 0 : delete poPassedLayer;
2060 0 : poPassedLayer = poLayer;
2061 : }
2062 :
2063 1 : if (bDisplayProgress)
2064 0 : GDALDestroyScaledProgress(pProgressArg);
2065 : }
2066 :
2067 :
2068 111 : if (bDisplayProgress)
2069 : {
2070 1 : if ( bSrcIsOSM )
2071 0 : pfnProgress = GDALTermProgress;
2072 : else
2073 : {
2074 1 : pfnProgress = GDALScaledProgress;
2075 1 : int nStart = 0;
2076 1 : if (poPassedLayer != poLayer && nMaxSplitListSubFields != 1)
2077 0 : nStart = panLayerCountFeatures[iLayer] / 2;
2078 : pProgressArg =
2079 : GDALCreateScaledProgress((nAccCountFeatures + nStart) * 1.0 / nCountLayersFeatures,
2080 1 : (nAccCountFeatures + panLayerCountFeatures[iLayer]) * 1.0 / nCountLayersFeatures,
2081 : GDALTermProgress,
2082 1 : NULL);
2083 : }
2084 : }
2085 :
2086 111 : nAccCountFeatures += panLayerCountFeatures[iLayer];
2087 :
2088 : TargetLayerInfo* psInfo = SetupTargetLayer( poDS,
2089 : poPassedLayer,
2090 : poODS,
2091 : papszLCO,
2092 : pszNewLayerName,
2093 : poOutputSRS,
2094 : bNullifyOutputSRS,
2095 : papszSelFields,
2096 : bAppend, eGType,
2097 : bPromoteToMulti,
2098 : nCoordDim, bOverwrite,
2099 : papszFieldTypesToString,
2100 : bExplodeCollections,
2101 : pszZField,
2102 : papszFieldMap,
2103 111 : pszWHERE );
2104 :
2105 111 : poPassedLayer->ResetReading();
2106 :
2107 111 : if( (psInfo == NULL ||
2108 : !TranslateLayer( psInfo, poDS, poPassedLayer, poODS,
2109 : bTransform, bWrapDateline, pszDateLineOffset,
2110 : poOutputSRS, bNullifyOutputSRS,
2111 : poSourceSRS,
2112 : poGCPCoordTrans,
2113 : eGType, bPromoteToMulti, nCoordDim,
2114 : eGeomOp, dfGeomOpParam,
2115 : panLayerCountFeatures[iLayer],
2116 : poClipSrc, poClipDst,
2117 : bExplodeCollections,
2118 : nSrcFileSize, NULL,
2119 : pfnProgress, pProgressArg ))
2120 : && !bSkipFailures )
2121 : {
2122 : CPLError( CE_Failure, CPLE_AppDefined,
2123 : "Terminating translation prematurely after failed\n"
2124 : "translation of layer %s (use -skipfailures to skip errors)\n",
2125 0 : poLayer->GetName() );
2126 :
2127 0 : exit( 1 );
2128 : }
2129 :
2130 111 : FreeTargetLayerInfo(psInfo);
2131 :
2132 111 : if (poPassedLayer != poLayer)
2133 1 : delete poPassedLayer;
2134 :
2135 111 : if (bDisplayProgress && !bSrcIsOSM)
2136 1 : GDALDestroyScaledProgress(pProgressArg);
2137 : }
2138 :
2139 79 : CPLFree(panLayerCountFeatures);
2140 79 : CPLFree(papoLayers);
2141 : }
2142 : /* -------------------------------------------------------------------- */
2143 : /* Process DS style table */
2144 : /* -------------------------------------------------------------------- */
2145 :
2146 89 : poODS->SetStyleTable( poDS->GetStyleTable () );
2147 :
2148 : /* -------------------------------------------------------------------- */
2149 : /* Close down. */
2150 : /* -------------------------------------------------------------------- */
2151 89 : if (bCloseODS)
2152 88 : OGRDataSource::DestroyDataSource(poODS);
2153 89 : OGRDataSource::DestroyDataSource(poDS);
2154 89 : OGRGeometryFactory::destroyGeometry(poSpatialFilter);
2155 89 : OGRGeometryFactory::destroyGeometry(poClipSrc);
2156 89 : OGRGeometryFactory::destroyGeometry(poClipDst);
2157 :
2158 89 : delete poGCPCoordTrans;
2159 89 : if( pasGCPs != NULL )
2160 : {
2161 5 : GDALDeinitGCPs( nGCPCount, pasGCPs );
2162 5 : CPLFree( pasGCPs );
2163 : }
2164 :
2165 : /* Destroy them after the last potential user */
2166 89 : OGRSpatialReference::DestroySpatialReference(poOutputSRS);
2167 89 : OGRSpatialReference::DestroySpatialReference(poSourceSRS);
2168 :
2169 89 : CSLDestroy(papszSelFields);
2170 89 : CSLDestroy( papszFieldMap );
2171 89 : CSLDestroy( papszArgv );
2172 89 : CSLDestroy( papszLayers );
2173 89 : CSLDestroy( papszDSCO );
2174 89 : CSLDestroy( papszLCO );
2175 89 : CSLDestroy( papszFieldTypesToString );
2176 89 : CPLFree( pszNewLayerName );
2177 :
2178 89 : OGRCleanupAll();
2179 :
2180 : #ifdef DBMALLOC
2181 : malloc_dump(1);
2182 : #endif
2183 :
2184 89 : return nRetCode;
2185 : }
2186 :
2187 : /************************************************************************/
2188 : /* Usage() */
2189 : /************************************************************************/
2190 :
2191 0 : static void Usage(int bShort)
2192 : {
2193 0 : Usage(NULL, bShort);
2194 0 : }
2195 :
2196 0 : static void Usage(const char* pszAdditionalMsg, int bShort)
2197 :
2198 : {
2199 0 : OGRSFDriverRegistrar *poR = OGRSFDriverRegistrar::GetRegistrar();
2200 :
2201 :
2202 : printf( "Usage: ogr2ogr [--help-general] [-skipfailures] [-append] [-update]\n"
2203 : " [-select field_list] [-where restricted_where]\n"
2204 : " [-progress] [-sql <sql statement>] [-dialect dialect]\n"
2205 : " [-preserve_fid] [-fid FID]\n"
2206 : " [-spat xmin ymin xmax ymax]\n"
2207 : " [-a_srs srs_def] [-t_srs srs_def] [-s_srs srs_def]\n"
2208 : " [-f format_name] [-overwrite] [[-dsco NAME=VALUE] ...]\n"
2209 : " dst_datasource_name src_datasource_name\n"
2210 : " [-lco NAME=VALUE] [-nln name] [-nlt type] [-dim 2|3] [layer [layer ...]]\n"
2211 : "\n"
2212 : "Advanced options :\n"
2213 : " [-gt n]\n"
2214 : " [-clipsrc [xmin ymin xmax ymax]|WKT|datasource|spat_extent]\n"
2215 : " [-clipsrcsql sql_statement] [-clipsrclayer layer]\n"
2216 : " [-clipsrcwhere expression]\n"
2217 : " [-clipdst [xmin ymin xmax ymax]|WKT|datasource]\n"
2218 : " [-clipdstsql sql_statement] [-clipdstlayer layer]\n"
2219 : " [-clipdstwhere expression]\n"
2220 : " [-wrapdateline][-datelineoffset val]\n"
2221 : " [[-simplify tolerance] | [-segmentize max_dist]]\n"
2222 : " [-fieldTypeToString All|(type1[,type2]*)]\n"
2223 : " [-fieldmap identity | index1[,index2]*]\n"
2224 : " [-splitlistfields] [-maxsubfields val]\n"
2225 : " [-explodecollections] [-zfield field_name]\n"
2226 0 : " [-gcp pixel line easting northing [elevation]]* [-order n | -tps]\n");
2227 :
2228 0 : if (bShort)
2229 : {
2230 0 : printf( "\nNote: ogr2ogr --long-usage for full help.\n");
2231 0 : if( pszAdditionalMsg )
2232 0 : fprintf(stderr, "\nFAILURE: %s\n", pszAdditionalMsg);
2233 0 : exit( 1 );
2234 : }
2235 :
2236 0 : printf("\n -f format_name: output file format name, possible values are:\n");
2237 :
2238 0 : for( int iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
2239 : {
2240 0 : OGRSFDriver *poDriver = poR->GetDriver(iDriver);
2241 :
2242 0 : if( poDriver->TestCapability( ODrCCreateDataSource ) )
2243 0 : printf( " -f \"%s\"\n", poDriver->GetName() );
2244 : }
2245 :
2246 : printf( " -append: Append to existing layer instead of creating new if it exists\n"
2247 : " -overwrite: delete the output layer and recreate it empty\n"
2248 : " -update: Open existing output datasource in update mode\n"
2249 : " -progress: Display progress on terminal. Only works if input layers have the \n"
2250 : " \"fast feature count\" capability\n"
2251 : " -select field_list: Comma-delimited list of fields from input layer to\n"
2252 : " copy to the new layer (defaults to all)\n"
2253 : " -where restricted_where: Attribute query (like SQL WHERE)\n"
2254 : " -wrapdateline: split geometries crossing the dateline meridian\n"
2255 : " (long. = +/- 180deg)\n"
2256 : " -datelineoffset: offset from dateline in degrees\n"
2257 : " (default long. = +/- 10deg,\n"
2258 : " geometries within 170deg to -170deg will be splited)\n"
2259 : " -sql statement: Execute given SQL statement and save result.\n"
2260 : " -dialect value: select a dialect, usually OGRSQL to avoid native sql.\n"
2261 : " -skipfailures: skip features or layers that fail to convert\n"
2262 : " -gt n: group n features per transaction (default 200)\n"
2263 : " -spat xmin ymin xmax ymax: spatial query extents\n"
2264 : " -simplify tolerance: distance tolerance for simplification.\n"
2265 : " -segmentize max_dist: maximum distance between 2 nodes.\n"
2266 : " Used to create intermediate points\n"
2267 : " -dsco NAME=VALUE: Dataset creation option (format specific)\n"
2268 : " -lco NAME=VALUE: Layer creation option (format specific)\n"
2269 : " -nln name: Assign an alternate name to the new layer\n"
2270 : " -nlt type: Force a geometry type for new layer. One of NONE, GEOMETRY,\n"
2271 : " POINT, LINESTRING, POLYGON, GEOMETRYCOLLECTION, MULTIPOINT,\n"
2272 : " MULTIPOLYGON, or MULTILINESTRING, or PROMOTE_TO_MULTI. Add \"25D\" for 3D layers.\n"
2273 : " Default is type of source layer.\n"
2274 : " -dim dimension: Force the coordinate dimension to the specified value.\n"
2275 : " -fieldTypeToString type1,...: Converts fields of specified types to\n"
2276 : " fields of type string in the new layer. Valid types are : Integer,\n"
2277 : " Real, String, Date, Time, DateTime, Binary, IntegerList, RealList,\n"
2278 : " StringList. Special value All will convert all fields to strings.\n"
2279 : " -fieldmap index1,index2,...: Specifies the list of field indexes to be\n"
2280 : " copied from the source to the destination. The (n)th value specified\n"
2281 : " in the list is the index of the field in the target layer definition\n"
2282 : " in which the n(th) field of the source layer must be copied. Index count\n"
2283 : " starts at zero. There must be exactly as many values in the list as\n"
2284 : " the count of the fields in the source layer. We can use the 'identity'\n"
2285 : " setting to specify that the fields should be transferred by using the\n"
2286 0 : " same order. This setting should be used along with the append setting.");
2287 :
2288 : printf(" -a_srs srs_def: Assign an output SRS\n"
2289 : " -t_srs srs_def: Reproject/transform to this SRS on output\n"
2290 : " -s_srs srs_def: Override source SRS\n"
2291 : "\n"
2292 : " Srs_def can be a full WKT definition (hard to escape properly),\n"
2293 : " or a well known definition (ie. EPSG:4326) or a file with a WKT\n"
2294 0 : " definition.\n" );
2295 :
2296 0 : if( pszAdditionalMsg )
2297 0 : fprintf(stderr, "\nFAILURE: %s\n", pszAdditionalMsg);
2298 :
2299 0 : exit( 1 );
2300 : }
2301 :
2302 : /************************************************************************/
2303 : /* SetZ() */
2304 : /************************************************************************/
2305 60 : static void SetZ (OGRGeometry* poGeom, double dfZ )
2306 : {
2307 60 : if (poGeom == NULL)
2308 0 : return;
2309 60 : switch (wkbFlatten(poGeom->getGeometryType()))
2310 : {
2311 : case wkbPoint:
2312 0 : ((OGRPoint*)poGeom)->setZ(dfZ);
2313 0 : break;
2314 :
2315 : case wkbLineString:
2316 : case wkbLinearRing:
2317 : {
2318 : int i;
2319 30 : OGRLineString* poLS = (OGRLineString*) poGeom;
2320 765 : for(i=0;i<poLS->getNumPoints();i++)
2321 735 : poLS->setPoint(i, poLS->getX(i), poLS->getY(i), dfZ);
2322 30 : break;
2323 : }
2324 :
2325 : case wkbPolygon:
2326 : {
2327 : int i;
2328 30 : OGRPolygon* poPoly = (OGRPolygon*) poGeom;
2329 30 : SetZ(poPoly->getExteriorRing(), dfZ);
2330 30 : for(i=0;i<poPoly->getNumInteriorRings();i++)
2331 0 : SetZ(poPoly->getInteriorRing(i), dfZ);
2332 30 : break;
2333 : }
2334 :
2335 : case wkbMultiPoint:
2336 : case wkbMultiLineString:
2337 : case wkbMultiPolygon:
2338 : case wkbGeometryCollection:
2339 : {
2340 : int i;
2341 0 : OGRGeometryCollection* poGeomColl = (OGRGeometryCollection*) poGeom;
2342 0 : for(i=0;i<poGeomColl->getNumGeometries();i++)
2343 0 : SetZ(poGeomColl->getGeometryRef(i), dfZ);
2344 : break;
2345 : }
2346 :
2347 : default:
2348 : break;
2349 : }
2350 : }
2351 :
2352 : /************************************************************************/
2353 : /* SetupTargetLayer() */
2354 : /************************************************************************/
2355 :
2356 130 : static TargetLayerInfo* SetupTargetLayer( OGRDataSource *poSrcDS,
2357 : OGRLayer * poSrcLayer,
2358 : OGRDataSource *poDstDS,
2359 : char **papszLCO,
2360 : const char *pszNewLayerName,
2361 : OGRSpatialReference *poOutputSRS,
2362 : int bNullifyOutputSRS,
2363 : char **papszSelFields,
2364 : int bAppend, int eGType,
2365 : int bPromoteToMulti,
2366 : int nCoordDim, int bOverwrite,
2367 : char** papszFieldTypesToString,
2368 : int bExplodeCollections,
2369 : const char* pszZField,
2370 : char **papszFieldMap,
2371 : const char* pszWHERE )
2372 : {
2373 : OGRLayer *poDstLayer;
2374 : OGRFeatureDefn *poSrcFDefn;
2375 130 : OGRFeatureDefn *poDstFDefn = NULL;
2376 :
2377 130 : if( pszNewLayerName == NULL )
2378 114 : pszNewLayerName = poSrcLayer->GetName();
2379 :
2380 : /* -------------------------------------------------------------------- */
2381 : /* Get other info. */
2382 : /* -------------------------------------------------------------------- */
2383 130 : poSrcFDefn = poSrcLayer->GetLayerDefn();
2384 :
2385 130 : if( poOutputSRS == NULL && !bNullifyOutputSRS )
2386 123 : poOutputSRS = poSrcLayer->GetSpatialRef();
2387 :
2388 : /* -------------------------------------------------------------------- */
2389 : /* Find the layer. */
2390 : /* -------------------------------------------------------------------- */
2391 :
2392 : /* GetLayerByName() can instanciate layers that would have been */
2393 : /* 'hidden' otherwise, for example, non-spatial tables in a */
2394 : /* Postgis-enabled database, so this apparently useless command is */
2395 : /* not useless... (#4012) */
2396 130 : CPLPushErrorHandler(CPLQuietErrorHandler);
2397 130 : poDstLayer = poDstDS->GetLayerByName(pszNewLayerName);
2398 130 : CPLPopErrorHandler();
2399 130 : CPLErrorReset();
2400 :
2401 130 : int iLayer = -1;
2402 130 : if (poDstLayer != NULL)
2403 : {
2404 15 : int nLayerCount = poDstDS->GetLayerCount();
2405 195 : for( iLayer = 0; iLayer < nLayerCount; iLayer++ )
2406 : {
2407 195 : OGRLayer *poLayer = poDstDS->GetLayer(iLayer);
2408 195 : if (poLayer == poDstLayer)
2409 15 : break;
2410 : }
2411 :
2412 15 : if (iLayer == nLayerCount)
2413 : /* shouldn't happen with an ideal driver */
2414 0 : poDstLayer = NULL;
2415 : }
2416 :
2417 : /* -------------------------------------------------------------------- */
2418 : /* If the user requested overwrite, and we have the layer in */
2419 : /* question we need to delete it now so it will get recreated */
2420 : /* (overwritten). */
2421 : /* -------------------------------------------------------------------- */
2422 130 : if( poDstLayer != NULL && bOverwrite )
2423 : {
2424 7 : if( poDstDS->DeleteLayer( iLayer ) != OGRERR_NONE )
2425 : {
2426 : fprintf( stderr,
2427 0 : "DeleteLayer() failed when overwrite requested.\n" );
2428 0 : return NULL;
2429 : }
2430 7 : poDstLayer = NULL;
2431 : }
2432 :
2433 : /* -------------------------------------------------------------------- */
2434 : /* If the layer does not exist, then create it. */
2435 : /* -------------------------------------------------------------------- */
2436 130 : if( poDstLayer == NULL )
2437 : {
2438 122 : if( eGType == -2 )
2439 : {
2440 115 : eGType = poSrcFDefn->GetGeomType();
2441 :
2442 115 : int n25DBit = eGType & wkb25DBit;
2443 115 : if ( bPromoteToMulti )
2444 : {
2445 2 : if (wkbFlatten(eGType) == wkbLineString)
2446 1 : eGType = wkbMultiLineString | n25DBit;
2447 1 : else if (wkbFlatten(eGType) == wkbPolygon)
2448 1 : eGType = wkbMultiPolygon | n25DBit;
2449 : }
2450 :
2451 115 : if ( bExplodeCollections )
2452 : {
2453 1 : if (wkbFlatten(eGType) == wkbMultiPoint)
2454 : {
2455 0 : eGType = wkbPoint | n25DBit;
2456 : }
2457 1 : else if (wkbFlatten(eGType) == wkbMultiLineString)
2458 : {
2459 0 : eGType = wkbLineString | n25DBit;
2460 : }
2461 1 : else if (wkbFlatten(eGType) == wkbMultiPolygon)
2462 : {
2463 0 : eGType = wkbPolygon | n25DBit;
2464 : }
2465 1 : else if (wkbFlatten(eGType) == wkbGeometryCollection)
2466 : {
2467 0 : eGType = wkbUnknown | n25DBit;
2468 : }
2469 : }
2470 :
2471 115 : if ( pszZField )
2472 3 : eGType |= wkb25DBit;
2473 : }
2474 :
2475 122 : if( nCoordDim == 2 )
2476 1 : eGType &= ~wkb25DBit;
2477 121 : else if( nCoordDim == 3 )
2478 1 : eGType |= wkb25DBit;
2479 :
2480 122 : if( !poDstDS->TestCapability( ODsCCreateLayer ) )
2481 : {
2482 : fprintf( stderr,
2483 : "Layer %s not found, and CreateLayer not supported by driver.",
2484 0 : pszNewLayerName );
2485 0 : return NULL;
2486 : }
2487 :
2488 122 : CPLErrorReset();
2489 :
2490 : poDstLayer = poDstDS->CreateLayer( pszNewLayerName, poOutputSRS,
2491 : (OGRwkbGeometryType) eGType,
2492 122 : papszLCO );
2493 :
2494 122 : if( poDstLayer == NULL )
2495 0 : return NULL;
2496 :
2497 122 : bAppend = FALSE;
2498 : }
2499 :
2500 : /* -------------------------------------------------------------------- */
2501 : /* Otherwise we will append to it, if append was requested. */
2502 : /* -------------------------------------------------------------------- */
2503 8 : else if( !bAppend )
2504 : {
2505 : fprintf( stderr, "FAILED: Layer %s already exists, and -append not specified.\n"
2506 : " Consider using -append, or -overwrite.\n",
2507 0 : pszNewLayerName );
2508 0 : return NULL;
2509 : }
2510 : else
2511 : {
2512 8 : if( CSLCount(papszLCO) > 0 )
2513 : {
2514 : fprintf( stderr, "WARNING: Layer creation options ignored since an existing layer is\n"
2515 0 : " being appended to.\n" );
2516 : }
2517 : }
2518 :
2519 : /* -------------------------------------------------------------------- */
2520 : /* Process Layer style table */
2521 : /* -------------------------------------------------------------------- */
2522 :
2523 130 : poDstLayer->SetStyleTable( poSrcLayer->GetStyleTable () );
2524 : /* -------------------------------------------------------------------- */
2525 : /* Add fields. Default to copy all field. */
2526 : /* If only a subset of all fields requested, then output only */
2527 : /* the selected fields, and in the order that they were */
2528 : /* selected. */
2529 : /* -------------------------------------------------------------------- */
2530 130 : int nSrcFieldCount = poSrcFDefn->GetFieldCount();
2531 : int iField, *panMap;
2532 :
2533 : // Initialize the index-to-index map to -1's
2534 130 : panMap = (int *) VSIMalloc( sizeof(int) * nSrcFieldCount );
2535 902 : for( iField=0; iField < nSrcFieldCount; iField++)
2536 772 : panMap[iField] = -1;
2537 :
2538 : /* Caution : at the time of writing, the MapInfo driver */
2539 : /* returns NULL until a field has been added */
2540 130 : poDstFDefn = poDstLayer->GetLayerDefn();
2541 :
2542 132 : if (papszFieldMap && bAppend)
2543 : {
2544 2 : int bIdentity = FALSE;
2545 :
2546 2 : if (EQUAL(papszFieldMap[0], "identity"))
2547 1 : bIdentity = TRUE;
2548 1 : else if (CSLCount(papszFieldMap) != nSrcFieldCount)
2549 : {
2550 0 : fprintf( stderr, "Field map should contain the value 'identity' or the same number of integer values as the source field count.\n");
2551 0 : VSIFree(panMap);
2552 0 : return NULL;
2553 : }
2554 :
2555 32 : for( iField=0; iField < nSrcFieldCount; iField++)
2556 : {
2557 30 : panMap[iField] = bIdentity? iField : atoi(papszFieldMap[iField]);
2558 30 : if (panMap[iField] >= poDstFDefn->GetFieldCount())
2559 : {
2560 0 : fprintf( stderr, "Invalid destination field index %d.\n", panMap[iField]);
2561 0 : VSIFree(panMap);
2562 0 : return NULL;
2563 : }
2564 : }
2565 : }
2566 135 : else if (papszSelFields && !bAppend )
2567 : {
2568 7 : int nDstFieldCount = 0;
2569 7 : if (poDstFDefn)
2570 6 : nDstFieldCount = poDstFDefn->GetFieldCount();
2571 18 : for( iField=0; papszSelFields[iField] != NULL; iField++)
2572 : {
2573 11 : int iSrcField = poSrcFDefn->GetFieldIndex(papszSelFields[iField]);
2574 11 : if (iSrcField >= 0)
2575 : {
2576 11 : OGRFieldDefn* poSrcFieldDefn = poSrcFDefn->GetFieldDefn(iSrcField);
2577 11 : OGRFieldDefn oFieldDefn( poSrcFieldDefn );
2578 :
2579 11 : if (papszFieldTypesToString != NULL &&
2580 : (CSLFindString(papszFieldTypesToString, "All") != -1 ||
2581 : CSLFindString(papszFieldTypesToString,
2582 : OGRFieldDefn::GetFieldTypeName(poSrcFieldDefn->GetType())) != -1))
2583 : {
2584 0 : oFieldDefn.SetType(OFTString);
2585 : }
2586 :
2587 : /* The field may have been already created at layer creation */
2588 11 : int iDstField = -1;
2589 11 : if (poDstFDefn)
2590 10 : iDstField = poDstFDefn->GetFieldIndex(oFieldDefn.GetNameRef());
2591 11 : if (iDstField >= 0)
2592 : {
2593 0 : panMap[iSrcField] = iDstField;
2594 : }
2595 11 : else if (poDstLayer->CreateField( &oFieldDefn ) == OGRERR_NONE)
2596 : {
2597 : /* now that we've created a field, GetLayerDefn() won't return NULL */
2598 11 : if (poDstFDefn == NULL)
2599 1 : poDstFDefn = poDstLayer->GetLayerDefn();
2600 :
2601 : /* Sanity check : if it fails, the driver is buggy */
2602 11 : if (poDstFDefn != NULL &&
2603 : poDstFDefn->GetFieldCount() != nDstFieldCount + 1)
2604 : {
2605 : CPLError(CE_Warning, CPLE_AppDefined,
2606 : "The output driver has claimed to have added the %s field, but it did not!",
2607 0 : oFieldDefn.GetNameRef() );
2608 : }
2609 : else
2610 : {
2611 11 : panMap[iSrcField] = nDstFieldCount;
2612 11 : nDstFieldCount ++;
2613 : }
2614 11 : }
2615 : }
2616 : else
2617 : {
2618 : fprintf( stderr, "Field '%s' not found in source layer.\n",
2619 0 : papszSelFields[iField] );
2620 0 : if( !bSkipFailures )
2621 : {
2622 0 : VSIFree(panMap);
2623 0 : return NULL;
2624 : }
2625 : }
2626 : }
2627 :
2628 : /* -------------------------------------------------------------------- */
2629 : /* Use SetIgnoredFields() on source layer if available */
2630 : /* -------------------------------------------------------------------- */
2631 7 : if (poSrcLayer->TestCapability(OLCIgnoreFields))
2632 : {
2633 : int iSrcField;
2634 3 : char** papszIgnoredFields = NULL;
2635 3 : int bUseIgnoredFields = TRUE;
2636 3 : char** papszWHEREUsedFields = NULL;
2637 :
2638 3 : if (pszWHERE)
2639 : {
2640 : /* We must not ignore fields used in the -where expression (#4015) */
2641 2 : OGRFeatureQuery oFeatureQuery;
2642 2 : if ( oFeatureQuery.Compile( poSrcLayer->GetLayerDefn(), pszWHERE ) == OGRERR_NONE )
2643 : {
2644 2 : papszWHEREUsedFields = oFeatureQuery.GetUsedFields();
2645 : }
2646 : else
2647 : {
2648 0 : bUseIgnoredFields = FALSE;
2649 2 : }
2650 : }
2651 :
2652 12 : for(iSrcField=0;iSrcField<poSrcFDefn->GetFieldCount();iSrcField++)
2653 : {
2654 : const char* pszFieldName =
2655 9 : poSrcFDefn->GetFieldDefn(iSrcField)->GetNameRef();
2656 9 : int bFieldRequested = FALSE;
2657 16 : for( iField=0; papszSelFields[iField] != NULL; iField++)
2658 : {
2659 11 : if (EQUAL(pszFieldName, papszSelFields[iField]))
2660 : {
2661 4 : bFieldRequested = TRUE;
2662 4 : break;
2663 : }
2664 : }
2665 9 : bFieldRequested |= CSLFindString(papszWHEREUsedFields, pszFieldName) >= 0;
2666 9 : bFieldRequested |= (pszZField != NULL && EQUAL(pszFieldName, pszZField));
2667 :
2668 : /* If source field not requested, add it to ignored files list */
2669 9 : if (!bFieldRequested)
2670 4 : papszIgnoredFields = CSLAddString(papszIgnoredFields, pszFieldName);
2671 : }
2672 3 : if (bUseIgnoredFields)
2673 3 : poSrcLayer->SetIgnoredFields((const char**)papszIgnoredFields);
2674 3 : CSLDestroy(papszIgnoredFields);
2675 3 : CSLDestroy(papszWHEREUsedFields);
2676 : }
2677 : }
2678 121 : else if( !bAppend )
2679 : {
2680 115 : int nDstFieldCount = 0;
2681 115 : if (poDstFDefn)
2682 113 : nDstFieldCount = poDstFDefn->GetFieldCount();
2683 821 : for( iField = 0; iField < nSrcFieldCount; iField++ )
2684 : {
2685 706 : OGRFieldDefn* poSrcFieldDefn = poSrcFDefn->GetFieldDefn(iField);
2686 706 : OGRFieldDefn oFieldDefn( poSrcFieldDefn );
2687 :
2688 706 : if (papszFieldTypesToString != NULL &&
2689 : (CSLFindString(papszFieldTypesToString, "All") != -1 ||
2690 : CSLFindString(papszFieldTypesToString,
2691 : OGRFieldDefn::GetFieldTypeName(poSrcFieldDefn->GetType())) != -1))
2692 : {
2693 0 : oFieldDefn.SetType(OFTString);
2694 : }
2695 :
2696 : /* The field may have been already created at layer creation */
2697 706 : int iDstField = -1;
2698 706 : if (poDstFDefn)
2699 704 : iDstField = poDstFDefn->GetFieldIndex(oFieldDefn.GetNameRef());
2700 706 : if (iDstField >= 0)
2701 : {
2702 285 : panMap[iField] = iDstField;
2703 : }
2704 421 : else if (poDstLayer->CreateField( &oFieldDefn ) == OGRERR_NONE)
2705 : {
2706 : /* now that we've created a field, GetLayerDefn() won't return NULL */
2707 421 : if (poDstFDefn == NULL)
2708 2 : poDstFDefn = poDstLayer->GetLayerDefn();
2709 :
2710 : /* Sanity check : if it fails, the driver is buggy */
2711 421 : if (poDstFDefn != NULL &&
2712 : poDstFDefn->GetFieldCount() != nDstFieldCount + 1)
2713 : {
2714 : CPLError(CE_Warning, CPLE_AppDefined,
2715 : "The output driver has claimed to have added the %s field, but it did not!",
2716 0 : oFieldDefn.GetNameRef() );
2717 : }
2718 : else
2719 : {
2720 421 : panMap[iField] = nDstFieldCount;
2721 421 : nDstFieldCount ++;
2722 : }
2723 : }
2724 : }
2725 : }
2726 : else
2727 : {
2728 : /* For an existing layer, build the map by fetching the index in the destination */
2729 : /* layer for each source field */
2730 6 : if (poDstFDefn == NULL)
2731 : {
2732 0 : fprintf( stderr, "poDstFDefn == NULL.\n" );
2733 0 : VSIFree(panMap);
2734 0 : return NULL;
2735 : }
2736 :
2737 24 : for( iField = 0; iField < nSrcFieldCount; iField++ )
2738 : {
2739 18 : OGRFieldDefn* poSrcFieldDefn = poSrcFDefn->GetFieldDefn(iField);
2740 18 : int iDstField = poDstFDefn->GetFieldIndex(poSrcFieldDefn->GetNameRef());
2741 18 : if (iDstField >= 0)
2742 18 : panMap[iField] = iDstField;
2743 : else
2744 : CPLDebug("OGR2OGR", "Skipping field '%s' not found in destination layer '%s'.",
2745 0 : poSrcFieldDefn->GetNameRef(), poDstLayer->GetName() );
2746 : }
2747 : }
2748 :
2749 130 : int iSrcZField = -1;
2750 130 : if (pszZField != NULL)
2751 : {
2752 3 : iSrcZField = poSrcFDefn->GetFieldIndex(pszZField);
2753 : }
2754 :
2755 : TargetLayerInfo* psInfo = (TargetLayerInfo*)
2756 130 : CPLMalloc(sizeof(TargetLayerInfo));
2757 130 : psInfo->nFeaturesRead = 0;
2758 130 : psInfo->bPerFeatureCT = FALSE;
2759 130 : psInfo->poDstLayer = poDstLayer;
2760 130 : psInfo->poCT = NULL;
2761 130 : psInfo->papszTransformOptions = NULL;
2762 130 : psInfo->panMap = panMap;
2763 130 : psInfo->iSrcZField = iSrcZField;
2764 :
2765 130 : return psInfo;
2766 : }
2767 :
2768 : /************************************************************************/
2769 : /* FreeTargetLayerInfo() */
2770 : /************************************************************************/
2771 :
2772 130 : static void FreeTargetLayerInfo(TargetLayerInfo* psInfo)
2773 : {
2774 130 : if( psInfo == NULL )
2775 0 : return;
2776 130 : delete psInfo->poCT;
2777 130 : CSLDestroy(psInfo->papszTransformOptions);
2778 130 : CPLFree(psInfo->panMap);
2779 130 : CPLFree(psInfo);
2780 : }
2781 :
2782 : /************************************************************************/
2783 : /* TranslateLayer() */
2784 : /************************************************************************/
2785 :
2786 142 : static int TranslateLayer( TargetLayerInfo* psInfo,
2787 : OGRDataSource *poSrcDS,
2788 : OGRLayer * poSrcLayer,
2789 : OGRDataSource *poDstDS,
2790 : int bTransform,
2791 : int bWrapDateline,
2792 : const char* pszDateLineOffset,
2793 : OGRSpatialReference *poOutputSRS,
2794 : int bNullifyOutputSRS,
2795 : OGRSpatialReference *poUserSourceSRS,
2796 : OGRCoordinateTransformation *poGCPCoordTrans,
2797 : int eGType,
2798 : int bPromoteToMulti,
2799 : int nCoordDim,
2800 : GeomOperation eGeomOp,
2801 : double dfGeomOpParam,
2802 : long nCountLayerFeatures,
2803 : OGRGeometry* poClipSrc,
2804 : OGRGeometry *poClipDst,
2805 : int bExplodeCollections,
2806 : vsi_l_offset nSrcFileSize,
2807 : GIntBig* pnReadFeatureCount,
2808 : GDALProgressFunc pfnProgress,
2809 : void *pProgressArg )
2810 :
2811 : {
2812 : OGRLayer *poDstLayer;
2813 142 : int bForceToPolygon = FALSE;
2814 142 : int bForceToMultiPolygon = FALSE;
2815 142 : int bForceToMultiLineString = FALSE;
2816 142 : char** papszTransformOptions = NULL;
2817 142 : OGRCoordinateTransformation *poCT = NULL;
2818 142 : int *panMap = NULL;
2819 : int iSrcZField;
2820 :
2821 142 : poDstLayer = psInfo->poDstLayer;
2822 142 : panMap = psInfo->panMap;
2823 142 : iSrcZField = psInfo->iSrcZField;
2824 :
2825 142 : if( poOutputSRS == NULL && !bNullifyOutputSRS )
2826 135 : poOutputSRS = poSrcLayer->GetSpatialRef();
2827 :
2828 142 : if( wkbFlatten(eGType) == wkbPolygon )
2829 1 : bForceToPolygon = TRUE;
2830 141 : else if( wkbFlatten(eGType) == wkbMultiPolygon )
2831 2 : bForceToMultiPolygon = TRUE;
2832 139 : else if( wkbFlatten(eGType) == wkbMultiLineString )
2833 0 : bForceToMultiLineString = TRUE;
2834 :
2835 : /* -------------------------------------------------------------------- */
2836 : /* Transfer features. */
2837 : /* -------------------------------------------------------------------- */
2838 : OGRFeature *poFeature;
2839 142 : int nFeaturesInTransaction = 0;
2840 142 : GIntBig nCount = 0; /* written + failed */
2841 142 : GIntBig nFeaturesWritten = 0;
2842 :
2843 142 : if( nGroupTransactions )
2844 142 : poDstLayer->StartTransaction();
2845 :
2846 125925 : while( TRUE )
2847 : {
2848 126067 : OGRFeature *poDstFeature = NULL;
2849 :
2850 126067 : if( nFIDToFetch != OGRNullFID )
2851 : {
2852 : // Only fetch feature on first pass.
2853 2 : if( nFeaturesInTransaction == 0 )
2854 1 : poFeature = poSrcLayer->GetFeature(nFIDToFetch);
2855 : else
2856 1 : poFeature = NULL;
2857 : }
2858 : else
2859 126065 : poFeature = poSrcLayer->GetNextFeature();
2860 :
2861 126067 : if( poFeature == NULL )
2862 : break;
2863 :
2864 125925 : if( psInfo->nFeaturesRead == 0 || psInfo->bPerFeatureCT )
2865 : {
2866 : /* -------------------------------------------------------------------- */
2867 : /* Setup coordinate transformation if we need it. */
2868 : /* -------------------------------------------------------------------- */
2869 129 : OGRSpatialReference* poSourceSRS = NULL;
2870 :
2871 129 : poCT = NULL;
2872 129 : papszTransformOptions = NULL;
2873 :
2874 129 : if( bTransform )
2875 : {
2876 5 : if( psInfo->nFeaturesRead == 0 )
2877 : {
2878 4 : poSourceSRS = poUserSourceSRS;
2879 4 : if( poSourceSRS == NULL )
2880 3 : poSourceSRS = poSrcLayer->GetSpatialRef();
2881 : }
2882 5 : if( poSourceSRS == NULL )
2883 : {
2884 2 : OGRGeometry* poSrcGeometry = poFeature->GetGeometryRef();
2885 2 : if( poSrcGeometry )
2886 2 : poSourceSRS = poSrcGeometry->getSpatialReference();
2887 2 : psInfo->bPerFeatureCT = TRUE;
2888 : }
2889 :
2890 5 : if( poSourceSRS == NULL )
2891 : {
2892 : fprintf( stderr, "Can't transform coordinates, source layer has no\n"
2893 0 : "coordinate system. Use -s_srs to set one.\n" );
2894 0 : OGRFeature::DestroyFeature( poFeature );
2895 0 : return FALSE;
2896 : }
2897 :
2898 5 : CPLAssert( NULL != poSourceSRS );
2899 5 : CPLAssert( NULL != poOutputSRS );
2900 :
2901 6 : if( psInfo->poCT != NULL &&
2902 1 : psInfo->poCT->GetSourceCS() == poSourceSRS )
2903 : {
2904 0 : poCT = psInfo->poCT;
2905 : }
2906 : else
2907 : {
2908 5 : poCT = OGRCreateCoordinateTransformation( poSourceSRS, poOutputSRS );
2909 5 : if( poCT == NULL )
2910 : {
2911 0 : char *pszWKT = NULL;
2912 :
2913 : fprintf( stderr, "Failed to create coordinate transformation between the\n"
2914 : "following coordinate systems. This may be because they\n"
2915 : "are not transformable, or because projection services\n"
2916 0 : "(PROJ.4 DLL/.so) could not be loaded.\n" );
2917 :
2918 0 : poSourceSRS->exportToPrettyWkt( &pszWKT, FALSE );
2919 0 : fprintf( stderr, "Source:\n%s\n", pszWKT );
2920 0 : CPLFree(pszWKT);
2921 :
2922 0 : poOutputSRS->exportToPrettyWkt( &pszWKT, FALSE );
2923 0 : fprintf( stderr, "Target:\n%s\n", pszWKT );
2924 0 : CPLFree(pszWKT);
2925 :
2926 0 : OGRFeature::DestroyFeature( poFeature );
2927 0 : return FALSE;
2928 : }
2929 5 : if( poGCPCoordTrans != NULL )
2930 1 : poCT = new CompositeCT( poGCPCoordTrans, poCT );
2931 : }
2932 :
2933 5 : if( poCT != psInfo->poCT )
2934 : {
2935 5 : delete psInfo->poCT;
2936 5 : psInfo->poCT = poCT;
2937 : }
2938 : }
2939 : else
2940 : {
2941 124 : poCT = poGCPCoordTrans;
2942 : }
2943 :
2944 129 : if (bWrapDateline)
2945 : {
2946 4 : if( poSourceSRS == NULL )
2947 : {
2948 3 : if( psInfo->nFeaturesRead == 0 )
2949 : {
2950 3 : poSourceSRS = poUserSourceSRS;
2951 3 : if( poSourceSRS == NULL )
2952 3 : poSourceSRS = poSrcLayer->GetSpatialRef();
2953 : }
2954 3 : if( poSourceSRS == NULL )
2955 : {
2956 0 : OGRGeometry* poSrcGeometry = poFeature->GetGeometryRef();
2957 0 : if( poSrcGeometry )
2958 0 : poSourceSRS = poSrcGeometry->getSpatialReference();
2959 0 : psInfo->bPerFeatureCT = TRUE;
2960 : }
2961 : }
2962 :
2963 4 : if (bTransform && poCT != NULL && poOutputSRS != NULL && poOutputSRS->IsGeographic())
2964 : {
2965 : papszTransformOptions =
2966 1 : CSLAddString(papszTransformOptions, "WRAPDATELINE=YES");
2967 1 : CPLString soOffset("DATELINEOFFSET=");
2968 1 : soOffset += pszDateLineOffset;
2969 : papszTransformOptions =
2970 1 : CSLAddString(papszTransformOptions, soOffset);
2971 : }
2972 3 : else if (poSourceSRS != NULL && poSourceSRS->IsGeographic())
2973 : {
2974 : papszTransformOptions =
2975 3 : CSLAddString(papszTransformOptions, "WRAPDATELINE=YES");
2976 3 : CPLString soOffset("DATELINEOFFSET=");
2977 3 : soOffset += pszDateLineOffset;
2978 : papszTransformOptions =
2979 3 : CSLAddString(papszTransformOptions, soOffset);
2980 : }
2981 : else
2982 : {
2983 : static int bHasWarned = FALSE;
2984 0 : if( !bHasWarned )
2985 0 : fprintf(stderr, "-wrapdateline option only works when reprojecting to a geographic SRS\n");
2986 0 : bHasWarned = TRUE;
2987 : }
2988 :
2989 4 : CSLDestroy(psInfo->papszTransformOptions);
2990 4 : psInfo->papszTransformOptions = papszTransformOptions;
2991 : }
2992 :
2993 : }
2994 :
2995 125925 : psInfo->nFeaturesRead ++;
2996 :
2997 125925 : int nParts = 0;
2998 125925 : int nIters = 1;
2999 125925 : if (bExplodeCollections)
3000 : {
3001 2 : OGRGeometry* poSrcGeometry = poFeature->GetGeometryRef();
3002 2 : if (poSrcGeometry)
3003 : {
3004 2 : switch (wkbFlatten(poSrcGeometry->getGeometryType()))
3005 : {
3006 : case wkbMultiPoint:
3007 : case wkbMultiLineString:
3008 : case wkbMultiPolygon:
3009 : case wkbGeometryCollection:
3010 1 : nParts = ((OGRGeometryCollection*)poSrcGeometry)->getNumGeometries();
3011 1 : nIters = nParts;
3012 1 : if (nIters == 0)
3013 0 : nIters = 1;
3014 : default:
3015 : break;
3016 : }
3017 : }
3018 : }
3019 :
3020 251851 : for(int iPart = 0; iPart < nIters; iPart++)
3021 : {
3022 125926 : if( ++nFeaturesInTransaction == nGroupTransactions )
3023 : {
3024 630 : poDstLayer->CommitTransaction();
3025 630 : poDstLayer->StartTransaction();
3026 630 : nFeaturesInTransaction = 0;
3027 : }
3028 :
3029 125926 : CPLErrorReset();
3030 125926 : poDstFeature = OGRFeature::CreateFeature( poDstLayer->GetLayerDefn() );
3031 :
3032 : /* Optimization to avoid duplicating the source geometry in the */
3033 : /* target feature : we steal it from the source feature for now... */
3034 125926 : OGRGeometry* poStealedGeometry = NULL;
3035 125926 : if( !bExplodeCollections )
3036 125923 : poStealedGeometry = poFeature->StealGeometry();
3037 :
3038 125926 : if( poDstFeature->SetFrom( poFeature, panMap, TRUE ) != OGRERR_NONE )
3039 : {
3040 0 : if( nGroupTransactions )
3041 0 : poDstLayer->CommitTransaction();
3042 :
3043 : CPLError( CE_Failure, CPLE_AppDefined,
3044 : "Unable to translate feature %ld from layer %s.\n",
3045 0 : poFeature->GetFID(), poSrcLayer->GetName() );
3046 :
3047 0 : OGRFeature::DestroyFeature( poFeature );
3048 0 : OGRFeature::DestroyFeature( poDstFeature );
3049 0 : OGRGeometryFactory::destroyGeometry( poStealedGeometry );
3050 0 : return FALSE;
3051 : }
3052 :
3053 : /* ... and now we can attach the stealed geometry */
3054 125926 : if( poStealedGeometry )
3055 24406 : poDstFeature->SetGeometryDirectly(poStealedGeometry);
3056 :
3057 125926 : if( bPreserveFID )
3058 0 : poDstFeature->SetFID( poFeature->GetFID() );
3059 :
3060 125926 : OGRGeometry* poDstGeometry = poDstFeature->GetGeometryRef();
3061 125926 : if (poDstGeometry != NULL)
3062 : {
3063 24409 : if (nParts > 0)
3064 : {
3065 : /* For -explodecollections, extract the iPart(th) of the geometry */
3066 2 : OGRGeometry* poPart = ((OGRGeometryCollection*)poDstGeometry)->getGeometryRef(iPart);
3067 2 : ((OGRGeometryCollection*)poDstGeometry)->removeGeometry(iPart, FALSE);
3068 2 : poDstFeature->SetGeometryDirectly(poPart);
3069 2 : poDstGeometry = poPart;
3070 : }
3071 :
3072 24409 : if (iSrcZField != -1)
3073 : {
3074 30 : SetZ(poDstGeometry, poFeature->GetFieldAsDouble(iSrcZField));
3075 : /* This will correct the coordinate dimension to 3 */
3076 30 : OGRGeometry* poDupGeometry = poDstGeometry->clone();
3077 30 : poDstFeature->SetGeometryDirectly(poDupGeometry);
3078 30 : poDstGeometry = poDupGeometry;
3079 : }
3080 :
3081 24409 : if (nCoordDim == 2 || nCoordDim == 3)
3082 20 : poDstGeometry->setCoordinateDimension( nCoordDim );
3083 :
3084 24409 : if (eGeomOp == SEGMENTIZE)
3085 : {
3086 10 : if (dfGeomOpParam > 0)
3087 10 : poDstGeometry->segmentize(dfGeomOpParam);
3088 : }
3089 24399 : else if (eGeomOp == SIMPLIFY_PRESERVE_TOPOLOGY)
3090 : {
3091 0 : if (dfGeomOpParam > 0)
3092 : {
3093 0 : OGRGeometry* poNewGeom = poDstGeometry->SimplifyPreserveTopology(dfGeomOpParam);
3094 0 : if (poNewGeom)
3095 : {
3096 0 : poDstFeature->SetGeometryDirectly(poNewGeom);
3097 0 : poDstGeometry = poNewGeom;
3098 : }
3099 : }
3100 : }
3101 :
3102 24409 : if (poClipSrc)
3103 : {
3104 24 : OGRGeometry* poClipped = poDstGeometry->Intersection(poClipSrc);
3105 24 : if (poClipped == NULL || poClipped->IsEmpty())
3106 : {
3107 12 : OGRGeometryFactory::destroyGeometry(poClipped);
3108 12 : goto end_loop;
3109 : }
3110 12 : poDstFeature->SetGeometryDirectly(poClipped);
3111 12 : poDstGeometry = poClipped;
3112 : }
3113 :
3114 24423 : if( poCT != NULL || papszTransformOptions != NULL)
3115 : {
3116 : OGRGeometry* poReprojectedGeom =
3117 26 : OGRGeometryFactory::transformWithOptions(poDstGeometry, poCT, papszTransformOptions);
3118 26 : if( poReprojectedGeom == NULL )
3119 : {
3120 0 : if( nGroupTransactions )
3121 0 : poDstLayer->CommitTransaction();
3122 :
3123 : fprintf( stderr, "Failed to reproject feature %d (geometry probably out of source or destination SRS).\n",
3124 0 : (int) poFeature->GetFID() );
3125 0 : if( !bSkipFailures )
3126 : {
3127 0 : OGRFeature::DestroyFeature( poFeature );
3128 0 : OGRFeature::DestroyFeature( poDstFeature );
3129 0 : return FALSE;
3130 : }
3131 : }
3132 :
3133 26 : poDstFeature->SetGeometryDirectly(poReprojectedGeom);
3134 26 : poDstGeometry = poReprojectedGeom;
3135 : }
3136 24371 : else if (poOutputSRS != NULL)
3137 : {
3138 24313 : poDstGeometry->assignSpatialReference(poOutputSRS);
3139 : }
3140 :
3141 24397 : if (poClipDst)
3142 : {
3143 20 : OGRGeometry* poClipped = poDstGeometry->Intersection(poClipDst);
3144 20 : if (poClipped == NULL || poClipped->IsEmpty())
3145 : {
3146 12 : OGRGeometryFactory::destroyGeometry(poClipped);
3147 12 : goto end_loop;
3148 : }
3149 :
3150 8 : poDstFeature->SetGeometryDirectly(poClipped);
3151 8 : poDstGeometry = poClipped;
3152 : }
3153 :
3154 24385 : if( bForceToPolygon )
3155 : {
3156 : poDstFeature->SetGeometryDirectly(
3157 : OGRGeometryFactory::forceToPolygon(
3158 10 : poDstFeature->StealGeometry() ) );
3159 : }
3160 24379 : else if( bForceToMultiPolygon ||
3161 4 : (bPromoteToMulti && wkbFlatten(poDstGeometry->getGeometryType()) == wkbPolygon) )
3162 : {
3163 : poDstFeature->SetGeometryDirectly(
3164 : OGRGeometryFactory::forceToMultiPolygon(
3165 15 : poDstFeature->StealGeometry() ) );
3166 : }
3167 24363 : else if ( bForceToMultiLineString ||
3168 3 : (bPromoteToMulti && wkbFlatten(poDstGeometry->getGeometryType()) == wkbLineString) )
3169 : {
3170 : poDstFeature->SetGeometryDirectly(
3171 : OGRGeometryFactory::forceToMultiLineString(
3172 1 : poDstFeature->StealGeometry() ) );
3173 : }
3174 : }
3175 :
3176 125902 : CPLErrorReset();
3177 125902 : if( poDstLayer->CreateFeature( poDstFeature ) == OGRERR_NONE )
3178 : {
3179 125902 : nFeaturesWritten ++;
3180 : }
3181 0 : else if( !bSkipFailures )
3182 : {
3183 0 : if( nGroupTransactions )
3184 0 : poDstLayer->RollbackTransaction();
3185 :
3186 0 : OGRFeature::DestroyFeature( poFeature );
3187 0 : OGRFeature::DestroyFeature( poDstFeature );
3188 0 : return FALSE;
3189 : }
3190 :
3191 : end_loop:
3192 125926 : OGRFeature::DestroyFeature( poDstFeature );
3193 : }
3194 :
3195 125925 : OGRFeature::DestroyFeature( poFeature );
3196 :
3197 : /* Report progress */
3198 125925 : nCount ++;
3199 125925 : if (pfnProgress)
3200 : {
3201 34 : if (nSrcFileSize != 0)
3202 : {
3203 24 : if ((nCount % 1000) == 0)
3204 : {
3205 0 : OGRLayer* poFCLayer = poSrcDS->ExecuteSQL("GetBytesRead()", NULL, NULL);
3206 0 : if( poFCLayer != NULL )
3207 : {
3208 0 : OGRFeature* poFeat = poFCLayer->GetNextFeature();
3209 0 : if( poFeat )
3210 : {
3211 0 : const char* pszReadSize = poFeat->GetFieldAsString(0);
3212 0 : GUIntBig nReadSize = CPLScanUIntBig( pszReadSize, 32 );
3213 0 : pfnProgress(nReadSize * 1.0 / nSrcFileSize, "", pProgressArg);
3214 0 : OGRFeature::DestroyFeature( poFeat );
3215 : }
3216 : }
3217 0 : poSrcDS->ReleaseResultSet(poFCLayer);
3218 : }
3219 : }
3220 : else
3221 : {
3222 10 : pfnProgress(nCount * 1.0 / nCountLayerFeatures, "", pProgressArg);
3223 : }
3224 : }
3225 :
3226 125925 : if (pnReadFeatureCount)
3227 21 : *pnReadFeatureCount = nCount;
3228 : }
3229 :
3230 142 : if( nGroupTransactions )
3231 142 : poDstLayer->CommitTransaction();
3232 :
3233 : CPLDebug("OGR2OGR", CPL_FRMT_GIB " features written in layer '%s'",
3234 142 : nFeaturesWritten, poDstLayer->GetName());
3235 :
3236 142 : return TRUE;
3237 : }
3238 :
|