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