1 : /******************************************************************************
2 : * $Id: ogr2ogr.cpp 23530 2011-12-11 17:13:55Z rouault $
3 : *
4 : * Project: OpenGIS Simple Features Reference Implementation
5 : * Purpose: Simple client for translating between formats.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 1999, Frank Warmerdam
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "ogrsf_frmts.h"
31 : #include "ogr_p.h"
32 : #include "cpl_conv.h"
33 : #include "cpl_string.h"
34 : #include "ogr_api.h"
35 : #include "gdal.h"
36 :
37 : CPL_CVSID("$Id: ogr2ogr.cpp 23530 2011-12-11 17:13:55Z rouault $");
38 :
39 : static int bSkipFailures = FALSE;
40 : static int nGroupTransactions = 200;
41 : static int bPreserveFID = FALSE;
42 : static int nFIDToFetch = OGRNullFID;
43 :
44 : static void Usage(int bShort = TRUE);
45 :
46 : typedef enum
47 : {
48 : NONE,
49 : SEGMENTIZE,
50 : SIMPLIFY_PRESERVE_TOPOLOGY,
51 : } GeomOperation;
52 :
53 : static int TranslateLayer( OGRDataSource *poSrcDS,
54 : OGRLayer * poSrcLayer,
55 : OGRDataSource *poDstDS,
56 : char ** papszLSCO,
57 : const char *pszNewLayerName,
58 : int bTransform,
59 : OGRSpatialReference *poOutputSRS,
60 : int bNullifyOutputSRS,
61 : OGRSpatialReference *poSourceSRS,
62 : char **papszSelFields,
63 : int bAppend, int eGType,
64 : int bOverwrite,
65 : GeomOperation eGeomOp,
66 : double dfGeomOpParam,
67 : char** papszFieldTypesToString,
68 : long nCountLayerFeatures,
69 : int bWrapDateline,
70 : OGRGeometry* poClipSrc,
71 : OGRGeometry *poClipDst,
72 : int bExplodeCollections,
73 : const char* pszZField,
74 : const char* pszWHERE,
75 : GDALProgressFunc pfnProgress,
76 : void *pProgressArg);
77 :
78 :
79 : /* -------------------------------------------------------------------- */
80 : /* CheckDestDataSourceNameConsistency() */
81 : /* -------------------------------------------------------------------- */
82 :
83 : static
84 35 : void CheckDestDataSourceNameConsistency(const char* pszDestFilename,
85 : const char* pszDriverName)
86 : {
87 : int i;
88 35 : char* pszDestExtension = CPLStrdup(CPLGetExtension(pszDestFilename));
89 :
90 : /* TODO: Would be good to have driver metadata like for GDAL drivers ! */
91 : static const char* apszExtensions[][2] = { { "shp" , "ESRI Shapefile" },
92 : { "dbf" , "ESRI Shapefile" },
93 : { "sqlite" , "SQLite" },
94 : { "db" , "SQLite" },
95 : { "mif" , "MapInfo File" },
96 : { "tab" , "MapInfo File" },
97 : { "s57" , "S57" },
98 : { "bna" , "BNA" },
99 : { "csv" , "CSV" },
100 : { "gml" , "GML" },
101 : { "kml" , "KML/LIBKML" },
102 : { "kmz" , "LIBKML" },
103 : { "json" , "GeoJSON" },
104 : { "geojson", "GeoJSON" },
105 : { "dxf" , "DXF" },
106 : { "gdb" , "FileGDB" },
107 : { "pix" , "PCIDSK" },
108 : { "sql" , "PGDump" },
109 : { "gtm" , "GPSTrackMaker" },
110 : { "gmt" , "GMT" },
111 : { NULL, NULL }
112 : };
113 : static const char* apszBeginName[][2] = { { "PG:" , "PG" },
114 : { "MySQL:" , "MySQL" },
115 : { "CouchDB:" , "CouchDB" },
116 : { "GFT:" , "GFT" },
117 : { "MSSQL:" , "MSSQLSpatial" },
118 : { "ODBC:" , "ODBC" },
119 : { "OCI:" , "OCI" },
120 : { "SDE:" , "SDE" },
121 : { "WFS:" , "WFS" },
122 : { NULL, NULL }
123 : };
124 :
125 735 : for(i=0; apszExtensions[i][0] != NULL; i++)
126 : {
127 700 : if (EQUAL(pszDestExtension, apszExtensions[i][0]) && !EQUAL(pszDriverName, apszExtensions[i][1]))
128 : {
129 : fprintf(stderr,
130 : "Warning: The target file has a '%s' extension, which is normally used by the %s driver,\n"
131 : "but the requested output driver is %s. Is it really what you want ?\n",
132 : pszDestExtension,
133 : apszExtensions[i][1],
134 0 : pszDriverName);
135 0 : break;
136 : }
137 : }
138 :
139 350 : for(i=0; apszBeginName[i][0] != NULL; i++)
140 : {
141 315 : if (EQUALN(pszDestFilename, apszBeginName[i][0], strlen(apszBeginName[i][0])) &&
142 : !EQUAL(pszDriverName, apszBeginName[i][1]))
143 : {
144 : fprintf(stderr,
145 : "Warning: The target file has a name which is normally recognized by the %s driver,\n"
146 : "but the requested output driver is %s. Is it really what you want ?\n",
147 : apszBeginName[i][1],
148 0 : pszDriverName);
149 0 : break;
150 : }
151 : }
152 :
153 35 : CPLFree(pszDestExtension);
154 35 : }
155 :
156 : /************************************************************************/
157 : /* IsNumber() */
158 : /************************************************************************/
159 :
160 5 : static int IsNumber(const char* pszStr)
161 : {
162 5 : if (*pszStr == '-' || *pszStr == '+')
163 0 : pszStr ++;
164 5 : if (*pszStr == '.')
165 0 : pszStr ++;
166 5 : return (*pszStr >= '0' && *pszStr <= '9');
167 : }
168 :
169 : /************************************************************************/
170 : /* LoadGeometry() */
171 : /************************************************************************/
172 :
173 2 : static OGRGeometry* LoadGeometry( const char* pszDS,
174 : const char* pszSQL,
175 : const char* pszLyr,
176 : const char* pszWhere)
177 : {
178 : OGRDataSource *poDS;
179 : OGRLayer *poLyr;
180 : OGRFeature *poFeat;
181 2 : OGRGeometry *poGeom = NULL;
182 :
183 2 : poDS = OGRSFDriverRegistrar::Open( pszDS, FALSE );
184 2 : if (poDS == NULL)
185 0 : return NULL;
186 :
187 2 : if (pszSQL != NULL)
188 1 : poLyr = poDS->ExecuteSQL( pszSQL, NULL, NULL );
189 1 : else if (pszLyr != NULL)
190 0 : poLyr = poDS->GetLayerByName(pszLyr);
191 : else
192 1 : poLyr = poDS->GetLayer(0);
193 :
194 2 : if (poLyr == NULL)
195 : {
196 0 : fprintf( stderr, "Failed to identify source layer from datasource.\n" );
197 0 : OGRDataSource::DestroyDataSource(poDS);
198 0 : return NULL;
199 : }
200 :
201 2 : if (pszWhere)
202 1 : poLyr->SetAttributeFilter(pszWhere);
203 :
204 6 : while ((poFeat = poLyr->GetNextFeature()) != NULL)
205 : {
206 2 : OGRGeometry* poSrcGeom = poFeat->GetGeometryRef();
207 2 : if (poSrcGeom)
208 : {
209 2 : OGRwkbGeometryType eType = wkbFlatten( poSrcGeom->getGeometryType() );
210 :
211 2 : if (poGeom == NULL)
212 2 : poGeom = OGRGeometryFactory::createGeometry( wkbMultiPolygon );
213 :
214 2 : if( eType == wkbPolygon )
215 2 : ((OGRGeometryCollection*)poGeom)->addGeometry( poSrcGeom );
216 0 : else if( eType == wkbMultiPolygon )
217 : {
218 : int iGeom;
219 0 : int nGeomCount = OGR_G_GetGeometryCount( (OGRGeometryH)poSrcGeom );
220 :
221 0 : for( iGeom = 0; iGeom < nGeomCount; iGeom++ )
222 : {
223 : ((OGRGeometryCollection*)poGeom)->addGeometry(
224 0 : ((OGRGeometryCollection*)poSrcGeom)->getGeometryRef(iGeom) );
225 : }
226 : }
227 : else
228 : {
229 0 : fprintf( stderr, "ERROR: Geometry not of polygon type.\n" );
230 0 : OGRGeometryFactory::destroyGeometry(poGeom);
231 0 : OGRFeature::DestroyFeature(poFeat);
232 0 : if( pszSQL != NULL )
233 0 : poDS->ReleaseResultSet( poLyr );
234 0 : OGRDataSource::DestroyDataSource(poDS);
235 0 : return NULL;
236 : }
237 : }
238 :
239 2 : OGRFeature::DestroyFeature(poFeat);
240 : }
241 :
242 2 : if( pszSQL != NULL )
243 1 : poDS->ReleaseResultSet( poLyr );
244 2 : OGRDataSource::DestroyDataSource(poDS);
245 :
246 2 : return poGeom;
247 : }
248 :
249 :
250 : /************************************************************************/
251 : /* OGRSplitListFieldLayer */
252 : /************************************************************************/
253 :
254 : typedef struct
255 : {
256 : int iSrcIndex;
257 : OGRFieldType eType;
258 : int nMaxOccurences;
259 : int nWidth;
260 : } ListFieldDesc;
261 :
262 : class OGRSplitListFieldLayer : public OGRLayer
263 : {
264 : OGRLayer *poSrcLayer;
265 : OGRFeatureDefn *poFeatureDefn;
266 : ListFieldDesc *pasListFields;
267 : int nListFieldCount;
268 : int nMaxSplitListSubFields;
269 :
270 : OGRFeature *TranslateFeature(OGRFeature* poSrcFeature);
271 :
272 : public:
273 : OGRSplitListFieldLayer(OGRLayer* poSrcLayer,
274 : int nMaxSplitListSubFields);
275 : ~OGRSplitListFieldLayer();
276 :
277 : int BuildLayerDefn(GDALProgressFunc pfnProgress,
278 : void *pProgressArg);
279 :
280 : virtual OGRFeature *GetNextFeature();
281 : virtual OGRFeature *GetFeature(long nFID);
282 : virtual OGRFeatureDefn *GetLayerDefn();
283 :
284 1 : virtual void ResetReading() { poSrcLayer->ResetReading(); }
285 0 : virtual int TestCapability(const char*) { return FALSE; }
286 :
287 0 : virtual int GetFeatureCount( int bForce = TRUE )
288 : {
289 0 : return poSrcLayer->GetFeatureCount(bForce);
290 : }
291 :
292 1 : virtual OGRSpatialReference *GetSpatialRef()
293 : {
294 1 : return poSrcLayer->GetSpatialRef();
295 : }
296 :
297 0 : virtual OGRGeometry *GetSpatialFilter()
298 : {
299 0 : return poSrcLayer->GetSpatialFilter();
300 : }
301 :
302 1 : virtual OGRStyleTable *GetStyleTable()
303 : {
304 1 : return poSrcLayer->GetStyleTable();
305 : }
306 :
307 0 : virtual void SetSpatialFilter( OGRGeometry *poGeom )
308 : {
309 0 : poSrcLayer->SetSpatialFilter(poGeom);
310 0 : }
311 :
312 0 : virtual void SetSpatialFilterRect( double dfMinX, double dfMinY,
313 : double dfMaxX, double dfMaxY )
314 : {
315 0 : poSrcLayer->SetSpatialFilterRect(dfMinX, dfMinY, dfMaxX, dfMaxY);
316 0 : }
317 :
318 0 : virtual OGRErr SetAttributeFilter( const char *pszFilter )
319 : {
320 0 : return poSrcLayer->SetAttributeFilter(pszFilter);
321 : }
322 : };
323 :
324 : /************************************************************************/
325 : /* OGRSplitListFieldLayer() */
326 : /************************************************************************/
327 :
328 1 : OGRSplitListFieldLayer::OGRSplitListFieldLayer(OGRLayer* poSrcLayer,
329 1 : int nMaxSplitListSubFields)
330 : {
331 1 : this->poSrcLayer = poSrcLayer;
332 1 : if (nMaxSplitListSubFields < 0)
333 1 : nMaxSplitListSubFields = INT_MAX;
334 1 : this->nMaxSplitListSubFields = nMaxSplitListSubFields;
335 1 : poFeatureDefn = NULL;
336 1 : pasListFields = NULL;
337 1 : nListFieldCount = 0;
338 1 : }
339 :
340 : /************************************************************************/
341 : /* ~OGRSplitListFieldLayer() */
342 : /************************************************************************/
343 :
344 1 : OGRSplitListFieldLayer::~OGRSplitListFieldLayer()
345 : {
346 1 : if( poFeatureDefn )
347 1 : poFeatureDefn->Release();
348 :
349 1 : CPLFree(pasListFields);
350 1 : }
351 :
352 : /************************************************************************/
353 : /* BuildLayerDefn() */
354 : /************************************************************************/
355 :
356 1 : int OGRSplitListFieldLayer::BuildLayerDefn(GDALProgressFunc pfnProgress,
357 : void *pProgressArg)
358 : {
359 1 : CPLAssert(poFeatureDefn == NULL);
360 :
361 1 : OGRFeatureDefn* poSrcFieldDefn = poSrcLayer->GetLayerDefn();
362 :
363 1 : int nSrcFields = poSrcFieldDefn->GetFieldCount();
364 : pasListFields =
365 1 : (ListFieldDesc*)CPLCalloc(sizeof(ListFieldDesc), nSrcFields);
366 1 : nListFieldCount = 0;
367 : int i;
368 :
369 : /* Establish the list of fields of list type */
370 6 : for(i=0;i<nSrcFields;i++)
371 : {
372 5 : OGRFieldType eType = poSrcFieldDefn->GetFieldDefn(i)->GetType();
373 5 : if (eType == OFTIntegerList ||
374 : eType == OFTRealList ||
375 : eType == OFTStringList)
376 : {
377 3 : pasListFields[nListFieldCount].iSrcIndex = i;
378 3 : pasListFields[nListFieldCount].eType = eType;
379 3 : if (nMaxSplitListSubFields == 1)
380 0 : pasListFields[nListFieldCount].nMaxOccurences = 1;
381 3 : nListFieldCount++;
382 : }
383 : }
384 :
385 1 : if (nListFieldCount == 0)
386 0 : return FALSE;
387 :
388 : /* No need for full scan if the limit is 1. We just to have to create */
389 : /* one and a single one field */
390 1 : if (nMaxSplitListSubFields != 1)
391 : {
392 1 : poSrcLayer->ResetReading();
393 : OGRFeature* poSrcFeature;
394 :
395 1 : int nFeatureCount = 0;
396 1 : if (poSrcLayer->TestCapability(OLCFastFeatureCount))
397 1 : nFeatureCount = poSrcLayer->GetFeatureCount();
398 1 : int nFeatureIndex = 0;
399 :
400 : /* Scan the whole layer to compute the maximum number of */
401 : /* items for each field of list type */
402 3 : while( (poSrcFeature = poSrcLayer->GetNextFeature()) != NULL )
403 : {
404 4 : for(i=0;i<nListFieldCount;i++)
405 : {
406 3 : int nCount = 0;
407 : OGRField* psField =
408 3 : poSrcFeature->GetRawFieldRef(pasListFields[i].iSrcIndex);
409 3 : switch(pasListFields[i].eType)
410 : {
411 : case OFTIntegerList:
412 1 : nCount = psField->IntegerList.nCount;
413 1 : break;
414 : case OFTRealList:
415 1 : nCount = psField->RealList.nCount;
416 1 : break;
417 : case OFTStringList:
418 : {
419 1 : nCount = psField->StringList.nCount;
420 1 : char** paList = psField->StringList.paList;
421 : int j;
422 3 : for(j=0;j<nCount;j++)
423 : {
424 2 : int nWidth = strlen(paList[j]);
425 2 : if (nWidth > pasListFields[i].nWidth)
426 1 : pasListFields[i].nWidth = nWidth;
427 : }
428 1 : break;
429 : }
430 : default:
431 0 : CPLAssert(0);
432 : break;
433 : }
434 3 : if (nCount > pasListFields[i].nMaxOccurences)
435 : {
436 3 : if (nCount > nMaxSplitListSubFields)
437 0 : nCount = nMaxSplitListSubFields;
438 3 : pasListFields[i].nMaxOccurences = nCount;
439 : }
440 : }
441 1 : OGRFeature::DestroyFeature(poSrcFeature);
442 :
443 1 : nFeatureIndex ++;
444 1 : if (pfnProgress != NULL && nFeatureCount != 0)
445 0 : pfnProgress(nFeatureIndex * 1.0 / nFeatureCount, "", pProgressArg);
446 : }
447 : }
448 :
449 : /* Now let's build the target feature definition */
450 :
451 : poFeatureDefn =
452 1 : OGRFeatureDefn::CreateFeatureDefn( poSrcFieldDefn->GetName() );
453 1 : poFeatureDefn->Reference();
454 1 : poFeatureDefn->SetGeomType( poSrcFieldDefn->GetGeomType() );
455 :
456 1 : int iListField = 0;
457 6 : for(i=0;i<nSrcFields;i++)
458 : {
459 5 : OGRFieldType eType = poSrcFieldDefn->GetFieldDefn(i)->GetType();
460 8 : if (eType == OFTIntegerList ||
461 : eType == OFTRealList ||
462 : eType == OFTStringList)
463 : {
464 3 : int nMaxOccurences = pasListFields[iListField].nMaxOccurences;
465 3 : int nWidth = pasListFields[iListField].nWidth;
466 3 : iListField ++;
467 : int j;
468 3 : if (nMaxOccurences == 1)
469 : {
470 : OGRFieldDefn oFieldDefn(poSrcFieldDefn->GetFieldDefn(i)->GetNameRef(),
471 : (eType == OFTIntegerList) ? OFTInteger :
472 : (eType == OFTRealList) ? OFTReal :
473 0 : OFTString);
474 0 : poFeatureDefn->AddFieldDefn(&oFieldDefn);
475 : }
476 : else
477 : {
478 9 : for(j=0;j<nMaxOccurences;j++)
479 : {
480 6 : CPLString osFieldName;
481 : osFieldName.Printf("%s%d",
482 6 : poSrcFieldDefn->GetFieldDefn(i)->GetNameRef(), j+1);
483 : OGRFieldDefn oFieldDefn(osFieldName.c_str(),
484 : (eType == OFTIntegerList) ? OFTInteger :
485 : (eType == OFTRealList) ? OFTReal :
486 6 : OFTString);
487 6 : oFieldDefn.SetWidth(nWidth);
488 6 : poFeatureDefn->AddFieldDefn(&oFieldDefn);
489 : }
490 : }
491 : }
492 : else
493 : {
494 2 : poFeatureDefn->AddFieldDefn(poSrcFieldDefn->GetFieldDefn(i));
495 : }
496 : }
497 :
498 1 : return TRUE;
499 : }
500 :
501 :
502 : /************************************************************************/
503 : /* TranslateFeature() */
504 : /************************************************************************/
505 :
506 2 : OGRFeature *OGRSplitListFieldLayer::TranslateFeature(OGRFeature* poSrcFeature)
507 : {
508 2 : if (poSrcFeature == NULL)
509 1 : return NULL;
510 1 : if (poFeatureDefn == NULL)
511 0 : return poSrcFeature;
512 :
513 1 : OGRFeature* poFeature = OGRFeature::CreateFeature(poFeatureDefn);
514 1 : poFeature->SetFID(poSrcFeature->GetFID());
515 1 : poFeature->SetGeometryDirectly(poSrcFeature->StealGeometry());
516 1 : poFeature->SetStyleString(poFeature->GetStyleString());
517 :
518 1 : OGRFeatureDefn* poSrcFieldDefn = poSrcLayer->GetLayerDefn();
519 1 : int nSrcFields = poSrcFeature->GetFieldCount();
520 : int iSrcField;
521 1 : int iDstField = 0;
522 1 : int iListField = 0;
523 : int j;
524 6 : for(iSrcField=0;iSrcField<nSrcFields;iSrcField++)
525 : {
526 5 : OGRFieldType eType = poSrcFieldDefn->GetFieldDefn(iSrcField)->GetType();
527 5 : OGRField* psField = poSrcFeature->GetRawFieldRef(iSrcField);
528 5 : switch(eType)
529 : {
530 : case OFTIntegerList:
531 : {
532 1 : int nCount = psField->IntegerList.nCount;
533 1 : if (nCount > nMaxSplitListSubFields)
534 0 : nCount = nMaxSplitListSubFields;
535 1 : int* paList = psField->IntegerList.paList;
536 3 : for(j=0;j<nCount;j++)
537 2 : poFeature->SetField(iDstField + j, paList[j]);
538 1 : iDstField += pasListFields[iListField].nMaxOccurences;
539 1 : iListField++;
540 1 : break;
541 : }
542 : case OFTRealList:
543 : {
544 1 : int nCount = psField->RealList.nCount;
545 1 : if (nCount > nMaxSplitListSubFields)
546 0 : nCount = nMaxSplitListSubFields;
547 1 : double* paList = psField->RealList.paList;
548 3 : for(j=0;j<nCount;j++)
549 2 : poFeature->SetField(iDstField + j, paList[j]);
550 1 : iDstField += pasListFields[iListField].nMaxOccurences;
551 1 : iListField++;
552 1 : break;
553 : }
554 : case OFTStringList:
555 : {
556 1 : int nCount = psField->StringList.nCount;
557 1 : if (nCount > nMaxSplitListSubFields)
558 0 : nCount = nMaxSplitListSubFields;
559 1 : char** paList = psField->StringList.paList;
560 3 : for(j=0;j<nCount;j++)
561 2 : poFeature->SetField(iDstField + j, paList[j]);
562 1 : iDstField += pasListFields[iListField].nMaxOccurences;
563 1 : iListField++;
564 1 : break;
565 : }
566 : default:
567 2 : poFeature->SetField(iDstField, psField);
568 2 : iDstField ++;
569 : break;
570 : }
571 : }
572 :
573 1 : OGRFeature::DestroyFeature(poSrcFeature);
574 :
575 1 : return poFeature;
576 : }
577 :
578 : /************************************************************************/
579 : /* GetNextFeature() */
580 : /************************************************************************/
581 :
582 2 : OGRFeature *OGRSplitListFieldLayer::GetNextFeature()
583 : {
584 2 : return TranslateFeature(poSrcLayer->GetNextFeature());
585 : }
586 :
587 : /************************************************************************/
588 : /* GetFeature() */
589 : /************************************************************************/
590 :
591 0 : OGRFeature *OGRSplitListFieldLayer::GetFeature(long nFID)
592 : {
593 0 : return TranslateFeature(poSrcLayer->GetFeature(nFID));
594 : }
595 :
596 : /************************************************************************/
597 : /* GetLayerDefn() */
598 : /************************************************************************/
599 :
600 2 : OGRFeatureDefn* OGRSplitListFieldLayer::GetLayerDefn()
601 : {
602 2 : if (poFeatureDefn == NULL)
603 0 : return poSrcLayer->GetLayerDefn();
604 2 : return poFeatureDefn;
605 : }
606 :
607 : /************************************************************************/
608 : /* main() */
609 : /************************************************************************/
610 :
611 63 : int main( int nArgc, char ** papszArgv )
612 :
613 : {
614 63 : int bQuiet = FALSE;
615 63 : int bFormatExplicitelySet = FALSE;
616 63 : const char *pszFormat = "ESRI Shapefile";
617 63 : const char *pszDataSource = NULL;
618 63 : const char *pszDestDataSource = NULL;
619 63 : char **papszLayers = NULL;
620 63 : char **papszDSCO = NULL, **papszLCO = NULL;
621 63 : int bTransform = FALSE;
622 63 : int bAppend = FALSE, bUpdate = FALSE, bOverwrite = FALSE;
623 63 : const char *pszOutputSRSDef = NULL;
624 63 : const char *pszSourceSRSDef = NULL;
625 63 : OGRSpatialReference *poOutputSRS = NULL;
626 63 : int bNullifyOutputSRS = FALSE;
627 63 : OGRSpatialReference *poSourceSRS = NULL;
628 63 : char *pszNewLayerName = NULL;
629 63 : const char *pszWHERE = NULL;
630 63 : OGRGeometry *poSpatialFilter = NULL;
631 : const char *pszSelect;
632 63 : char **papszSelFields = NULL;
633 63 : const char *pszSQLStatement = NULL;
634 63 : const char *pszDialect = NULL;
635 63 : int eGType = -2;
636 63 : GeomOperation eGeomOp = NONE;
637 63 : double dfGeomOpParam = 0;
638 63 : char **papszFieldTypesToString = NULL;
639 63 : int bDisplayProgress = FALSE;
640 63 : GDALProgressFunc pfnProgress = NULL;
641 63 : void *pProgressArg = NULL;
642 63 : int bWrapDateline = FALSE;
643 63 : int bClipSrc = FALSE;
644 63 : OGRGeometry* poClipSrc = NULL;
645 63 : const char *pszClipSrcDS = NULL;
646 63 : const char *pszClipSrcSQL = NULL;
647 63 : const char *pszClipSrcLayer = NULL;
648 63 : const char *pszClipSrcWhere = NULL;
649 63 : OGRGeometry *poClipDst = NULL;
650 63 : const char *pszClipDstDS = NULL;
651 63 : const char *pszClipDstSQL = NULL;
652 63 : const char *pszClipDstLayer = NULL;
653 63 : const char *pszClipDstWhere = NULL;
654 63 : int bSplitListFields = FALSE;
655 63 : int nMaxSplitListSubFields = -1;
656 63 : int bExplodeCollections = FALSE;
657 63 : const char *pszZField = NULL;
658 :
659 : /* Check strict compilation and runtime library version as we use C++ API */
660 63 : if (! GDAL_CHECK_VERSION(papszArgv[0]))
661 0 : exit(1);
662 : /* -------------------------------------------------------------------- */
663 : /* Register format(s). */
664 : /* -------------------------------------------------------------------- */
665 63 : OGRRegisterAll();
666 :
667 : /* -------------------------------------------------------------------- */
668 : /* Processing command line arguments. */
669 : /* -------------------------------------------------------------------- */
670 63 : nArgc = OGRGeneralCmdLineProcessor( nArgc, &papszArgv, 0 );
671 :
672 63 : if( nArgc < 1 )
673 0 : exit( -nArgc );
674 :
675 289 : for( int iArg = 1; iArg < nArgc; iArg++ )
676 : {
677 227 : if( EQUAL(papszArgv[iArg], "--utility_version") )
678 : {
679 : printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
680 1 : papszArgv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
681 1 : return 0;
682 : }
683 226 : else if ( EQUAL(papszArgv[iArg], "--long-usage") )
684 : {
685 0 : Usage(FALSE);
686 : }
687 :
688 226 : else if( EQUAL(papszArgv[iArg],"-q") || EQUAL(papszArgv[iArg],"-quiet") )
689 : {
690 0 : bQuiet = TRUE;
691 : }
692 245 : else if( EQUAL(papszArgv[iArg],"-f") && iArg < nArgc-1 )
693 : {
694 19 : bFormatExplicitelySet = TRUE;
695 19 : pszFormat = papszArgv[++iArg];
696 : }
697 209 : else if( EQUAL(papszArgv[iArg],"-dsco") && iArg < nArgc-1 )
698 : {
699 2 : papszDSCO = CSLAddString(papszDSCO, papszArgv[++iArg] );
700 : }
701 206 : else if( EQUAL(papszArgv[iArg],"-lco") && iArg < nArgc-1 )
702 : {
703 1 : papszLCO = CSLAddString(papszLCO, papszArgv[++iArg] );
704 : }
705 204 : else if( EQUAL(papszArgv[iArg],"-preserve_fid") )
706 : {
707 0 : bPreserveFID = TRUE;
708 : }
709 204 : else if( EQUALN(papszArgv[iArg],"-skip",5) )
710 : {
711 0 : bSkipFailures = TRUE;
712 0 : nGroupTransactions = 1; /* #2409 */
713 : }
714 204 : else if( EQUAL(papszArgv[iArg],"-append") )
715 : {
716 6 : bAppend = TRUE;
717 6 : bUpdate = TRUE;
718 : }
719 198 : else if( EQUAL(papszArgv[iArg],"-overwrite") )
720 : {
721 11 : bOverwrite = TRUE;
722 11 : bUpdate = TRUE;
723 : }
724 187 : else if( EQUAL(papszArgv[iArg],"-update") )
725 : {
726 2 : bUpdate = TRUE;
727 : }
728 186 : else if( EQUAL(papszArgv[iArg],"-fid") && papszArgv[iArg+1] != NULL )
729 : {
730 1 : nFIDToFetch = atoi(papszArgv[++iArg]);
731 : }
732 190 : else if( EQUAL(papszArgv[iArg],"-sql") && papszArgv[iArg+1] != NULL )
733 : {
734 6 : pszSQLStatement = papszArgv[++iArg];
735 : }
736 178 : else if( EQUAL(papszArgv[iArg],"-dialect") && papszArgv[iArg+1] != NULL )
737 : {
738 0 : pszDialect = papszArgv[++iArg];
739 : }
740 189 : else if( EQUAL(papszArgv[iArg],"-nln") && iArg < nArgc-1 )
741 : {
742 11 : pszNewLayerName = CPLStrdup(papszArgv[++iArg]);
743 : }
744 174 : else if( EQUAL(papszArgv[iArg],"-nlt") && iArg < nArgc-1 )
745 : {
746 7 : int bIs3D = FALSE;
747 7 : CPLString osGeomName = papszArgv[iArg+1];
748 21 : if (strlen(papszArgv[iArg+1]) > 3 &&
749 14 : EQUALN(papszArgv[iArg+1] + strlen(papszArgv[iArg+1]) - 3, "25D", 3))
750 : {
751 1 : bIs3D = TRUE;
752 1 : osGeomName.resize(osGeomName.size() - 3);
753 : }
754 7 : if( EQUAL(osGeomName,"NONE") )
755 0 : eGType = wkbNone;
756 7 : else if( EQUAL(osGeomName,"GEOMETRY") )
757 0 : eGType = wkbUnknown;
758 : else
759 : {
760 7 : eGType = OGRFromOGCGeomType(osGeomName);
761 7 : if (eGType == wkbUnknown)
762 : {
763 : fprintf( stderr, "-nlt %s: type not recognised.\n",
764 0 : papszArgv[iArg+1] );
765 0 : exit( 1 );
766 : }
767 : }
768 7 : if (eGType != wkbNone && bIs3D)
769 1 : eGType |= wkb25DBit;
770 :
771 7 : iArg++;
772 : }
773 321 : else if( (EQUAL(papszArgv[iArg],"-tg") ||
774 160 : EQUAL(papszArgv[iArg],"-gt")) && iArg < nArgc-1 )
775 : {
776 1 : nGroupTransactions = atoi(papszArgv[++iArg]);
777 : }
778 159 : else if( EQUAL(papszArgv[iArg],"-s_srs") && iArg < nArgc-1 )
779 : {
780 0 : pszSourceSRSDef = papszArgv[++iArg];
781 : }
782 161 : else if( EQUAL(papszArgv[iArg],"-a_srs") && iArg < nArgc-1 )
783 : {
784 2 : pszOutputSRSDef = papszArgv[++iArg];
785 2 : if (EQUAL(pszOutputSRSDef, "NULL") ||
786 : EQUAL(pszOutputSRSDef, "NONE"))
787 : {
788 1 : pszOutputSRSDef = NULL;
789 1 : bNullifyOutputSRS = TRUE;
790 : }
791 : }
792 159 : else if( EQUAL(papszArgv[iArg],"-t_srs") && iArg < nArgc-1 )
793 : {
794 2 : pszOutputSRSDef = papszArgv[++iArg];
795 2 : bTransform = TRUE;
796 : }
797 165 : else if( EQUAL(papszArgv[iArg],"-spat")
798 2 : && papszArgv[iArg+1] != NULL
799 2 : && papszArgv[iArg+2] != NULL
800 2 : && papszArgv[iArg+3] != NULL
801 2 : && papszArgv[iArg+4] != NULL )
802 : {
803 2 : OGRLinearRing oRing;
804 :
805 2 : oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+2]) );
806 2 : oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+4]) );
807 2 : oRing.addPoint( atof(papszArgv[iArg+3]), atof(papszArgv[iArg+4]) );
808 2 : oRing.addPoint( atof(papszArgv[iArg+3]), atof(papszArgv[iArg+2]) );
809 2 : oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+2]) );
810 :
811 2 : poSpatialFilter = OGRGeometryFactory::createGeometry(wkbPolygon);
812 2 : ((OGRPolygon *) poSpatialFilter)->addRing( &oRing );
813 2 : iArg += 4;
814 : }
815 155 : else if( EQUAL(papszArgv[iArg],"-where") && papszArgv[iArg+1] != NULL )
816 : {
817 2 : pszWHERE = papszArgv[++iArg];
818 : }
819 157 : else if( EQUAL(papszArgv[iArg],"-select") && papszArgv[iArg+1] != NULL)
820 : {
821 6 : pszSelect = papszArgv[++iArg];
822 : papszSelFields = CSLTokenizeStringComplex(pszSelect, " ,",
823 6 : FALSE, FALSE );
824 : }
825 146 : else if( EQUAL(papszArgv[iArg],"-segmentize") && iArg < nArgc-1 )
826 : {
827 1 : eGeomOp = SEGMENTIZE;
828 1 : dfGeomOpParam = atof(papszArgv[++iArg]);
829 : }
830 144 : else if( EQUAL(papszArgv[iArg],"-simplify") && iArg < nArgc-1 )
831 : {
832 0 : eGeomOp = SIMPLIFY_PRESERVE_TOPOLOGY;
833 0 : dfGeomOpParam = atof(papszArgv[++iArg]);
834 : }
835 144 : else if( EQUAL(papszArgv[iArg],"-fieldTypeToString") && iArg < nArgc-1 )
836 : {
837 : papszFieldTypesToString =
838 0 : CSLTokenizeStringComplex(papszArgv[++iArg], " ,",
839 0 : FALSE, FALSE );
840 0 : char** iter = papszFieldTypesToString;
841 0 : while(*iter)
842 : {
843 0 : if (EQUAL(*iter, "Integer") ||
844 : EQUAL(*iter, "Real") ||
845 : EQUAL(*iter, "String") ||
846 : EQUAL(*iter, "Date") ||
847 : EQUAL(*iter, "Time") ||
848 : EQUAL(*iter, "DateTime") ||
849 : EQUAL(*iter, "Binary") ||
850 : EQUAL(*iter, "IntegerList") ||
851 : EQUAL(*iter, "RealList") ||
852 : EQUAL(*iter, "StringList"))
853 : {
854 : /* Do nothing */
855 : }
856 0 : else if (EQUAL(*iter, "All"))
857 : {
858 0 : CSLDestroy(papszFieldTypesToString);
859 0 : papszFieldTypesToString = NULL;
860 0 : papszFieldTypesToString = CSLAddString(papszFieldTypesToString, "All");
861 0 : break;
862 : }
863 : else
864 : {
865 : fprintf(stderr, "Unhandled type for fieldtypeasstring option : %s\n",
866 0 : *iter);
867 0 : Usage();
868 : }
869 0 : iter ++;
870 : }
871 : }
872 144 : else if( EQUAL(papszArgv[iArg],"-progress") )
873 : {
874 1 : bDisplayProgress = TRUE;
875 : }
876 143 : else if( EQUAL(papszArgv[iArg],"-wrapdateline") )
877 : {
878 4 : bWrapDateline = TRUE;
879 : }
880 142 : else if( EQUAL(papszArgv[iArg],"-clipsrc") && iArg < nArgc-1 )
881 : {
882 3 : bClipSrc = TRUE;
883 3 : if ( IsNumber(papszArgv[iArg+1])
884 0 : && papszArgv[iArg+2] != NULL
885 0 : && papszArgv[iArg+3] != NULL
886 0 : && papszArgv[iArg+4] != NULL)
887 : {
888 0 : OGRLinearRing oRing;
889 :
890 0 : oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+2]) );
891 0 : oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+4]) );
892 0 : oRing.addPoint( atof(papszArgv[iArg+3]), atof(papszArgv[iArg+4]) );
893 0 : oRing.addPoint( atof(papszArgv[iArg+3]), atof(papszArgv[iArg+2]) );
894 0 : oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+2]) );
895 :
896 0 : poClipSrc = OGRGeometryFactory::createGeometry(wkbPolygon);
897 0 : ((OGRPolygon *) poClipSrc)->addRing( &oRing );
898 0 : iArg += 4;
899 : }
900 6 : else if (EQUALN(papszArgv[iArg+1], "POLYGON", 7) ||
901 2 : EQUALN(papszArgv[iArg+1], "MULTIPOLYGON", 12))
902 : {
903 1 : char* pszTmp = (char*) papszArgv[iArg+1];
904 1 : OGRGeometryFactory::createFromWkt(&pszTmp, NULL, &poClipSrc);
905 1 : if (poClipSrc == NULL)
906 : {
907 0 : fprintf( stderr, "FAILURE: Invalid geometry. Must be a valid POLYGON or MULTIPOLYGON WKT\n\n");
908 0 : Usage();
909 : }
910 1 : iArg ++;
911 : }
912 2 : else if (EQUAL(papszArgv[iArg+1], "spat_extent") )
913 : {
914 1 : iArg ++;
915 : }
916 : else
917 : {
918 1 : pszClipSrcDS = papszArgv[iArg+1];
919 1 : iArg ++;
920 : }
921 : }
922 136 : else if( EQUAL(papszArgv[iArg],"-clipsrcsql") && iArg < nArgc-1 )
923 : {
924 0 : pszClipSrcSQL = papszArgv[iArg+1];
925 0 : iArg ++;
926 : }
927 136 : else if( EQUAL(papszArgv[iArg],"-clipsrclayer") && iArg < nArgc-1 )
928 : {
929 0 : pszClipSrcLayer = papszArgv[iArg+1];
930 0 : iArg ++;
931 : }
932 137 : else if( EQUAL(papszArgv[iArg],"-clipsrcwhere") && iArg < nArgc-1 )
933 : {
934 1 : pszClipSrcWhere = papszArgv[iArg+1];
935 1 : iArg ++;
936 : }
937 137 : else if( EQUAL(papszArgv[iArg],"-clipdst") && iArg < nArgc-1 )
938 : {
939 2 : if ( IsNumber(papszArgv[iArg+1])
940 0 : && papszArgv[iArg+2] != NULL
941 0 : && papszArgv[iArg+3] != NULL
942 0 : && papszArgv[iArg+4] != NULL)
943 : {
944 0 : OGRLinearRing oRing;
945 :
946 0 : oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+2]) );
947 0 : oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+4]) );
948 0 : oRing.addPoint( atof(papszArgv[iArg+3]), atof(papszArgv[iArg+4]) );
949 0 : oRing.addPoint( atof(papszArgv[iArg+3]), atof(papszArgv[iArg+2]) );
950 0 : oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+2]) );
951 :
952 0 : poClipDst = OGRGeometryFactory::createGeometry(wkbPolygon);
953 0 : ((OGRPolygon *) poClipDst)->addRing( &oRing );
954 0 : iArg += 4;
955 : }
956 4 : else if (EQUALN(papszArgv[iArg+1], "POLYGON", 7) ||
957 1 : EQUALN(papszArgv[iArg+1], "MULTIPOLYGON", 12))
958 : {
959 1 : char* pszTmp = (char*) papszArgv[iArg+1];
960 1 : OGRGeometryFactory::createFromWkt(&pszTmp, NULL, &poClipDst);
961 1 : if (poClipDst == NULL)
962 : {
963 0 : fprintf( stderr, "FAILURE: Invalid geometry. Must be a valid POLYGON or MULTIPOLYGON WKT\n\n");
964 0 : Usage();
965 : }
966 1 : iArg ++;
967 : }
968 : else
969 : {
970 1 : pszClipDstDS = papszArgv[iArg+1];
971 1 : iArg ++;
972 : }
973 : }
974 134 : else if( EQUAL(papszArgv[iArg],"-clipdstsql") && iArg < nArgc-1 )
975 : {
976 1 : pszClipDstSQL = papszArgv[iArg+1];
977 1 : iArg ++;
978 : }
979 132 : else if( EQUAL(papszArgv[iArg],"-clipdstlayer") && iArg < nArgc-1 )
980 : {
981 0 : pszClipDstLayer = papszArgv[iArg+1];
982 0 : iArg ++;
983 : }
984 132 : else if( EQUAL(papszArgv[iArg],"-clipdstwhere") && iArg < nArgc-1 )
985 : {
986 0 : pszClipDstWhere = papszArgv[iArg+1];
987 0 : iArg ++;
988 : }
989 132 : else if( EQUAL(papszArgv[iArg],"-splitlistfields") )
990 : {
991 1 : bSplitListFields = TRUE;
992 : }
993 131 : else if ( EQUAL(papszArgv[iArg],"-maxsubfields") && iArg < nArgc-1 )
994 : {
995 0 : if (IsNumber(papszArgv[iArg+1]))
996 : {
997 0 : int nTemp = atoi(papszArgv[iArg+1]);
998 0 : if (nTemp > 0)
999 : {
1000 0 : nMaxSplitListSubFields = nTemp;
1001 0 : iArg ++;
1002 : }
1003 : }
1004 : }
1005 131 : else if( EQUAL(papszArgv[iArg],"-explodecollections") )
1006 : {
1007 1 : bExplodeCollections = TRUE;
1008 : }
1009 133 : else if( EQUAL(papszArgv[iArg],"-zfield") && iArg < nArgc-1 )
1010 : {
1011 3 : pszZField = papszArgv[iArg+1];
1012 3 : iArg ++;
1013 : }
1014 127 : else if( papszArgv[iArg][0] == '-' )
1015 : {
1016 0 : Usage();
1017 : }
1018 127 : else if( pszDestDataSource == NULL )
1019 62 : pszDestDataSource = papszArgv[iArg];
1020 65 : else if( pszDataSource == NULL )
1021 62 : pszDataSource = papszArgv[iArg];
1022 : else
1023 3 : papszLayers = CSLAddString( papszLayers, papszArgv[iArg] );
1024 : }
1025 :
1026 62 : if( pszDataSource == NULL )
1027 0 : Usage();
1028 :
1029 62 : if( bPreserveFID && bExplodeCollections )
1030 : {
1031 0 : fprintf( stderr, "FAILURE: cannot use -preserve_fid and -explodecollections at the same time\n\n" );
1032 0 : Usage();
1033 : }
1034 :
1035 63 : if( bClipSrc && pszClipSrcDS != NULL)
1036 : {
1037 1 : poClipSrc = LoadGeometry(pszClipSrcDS, pszClipSrcSQL, pszClipSrcLayer, pszClipSrcWhere);
1038 1 : if (poClipSrc == NULL)
1039 : {
1040 0 : fprintf( stderr, "FAILURE: cannot load source clip geometry\n\n" );
1041 0 : Usage();
1042 : }
1043 : }
1044 61 : else if( bClipSrc && poClipSrc == NULL )
1045 : {
1046 1 : if (poSpatialFilter)
1047 1 : poClipSrc = poSpatialFilter->clone();
1048 1 : if (poClipSrc == NULL)
1049 : {
1050 : fprintf( stderr, "FAILURE: -clipsrc must be used with -spat option or a\n"
1051 0 : "bounding box, WKT string or datasource must be specified\n\n");
1052 0 : Usage();
1053 : }
1054 : }
1055 :
1056 62 : if( pszClipDstDS != NULL)
1057 : {
1058 1 : poClipDst = LoadGeometry(pszClipDstDS, pszClipDstSQL, pszClipDstLayer, pszClipDstWhere);
1059 1 : if (poClipDst == NULL)
1060 : {
1061 0 : fprintf( stderr, "FAILURE: cannot load dest clip geometry\n\n" );
1062 0 : Usage();
1063 : }
1064 : }
1065 :
1066 : /* -------------------------------------------------------------------- */
1067 : /* Open data source. */
1068 : /* -------------------------------------------------------------------- */
1069 : OGRDataSource *poDS;
1070 :
1071 62 : poDS = OGRSFDriverRegistrar::Open( pszDataSource, FALSE );
1072 :
1073 : /* -------------------------------------------------------------------- */
1074 : /* Report failure */
1075 : /* -------------------------------------------------------------------- */
1076 62 : if( poDS == NULL )
1077 : {
1078 0 : OGRSFDriverRegistrar *poR = OGRSFDriverRegistrar::GetRegistrar();
1079 :
1080 : fprintf( stderr, "FAILURE:\n"
1081 : "Unable to open datasource `%s' with the following drivers.\n",
1082 0 : pszDataSource );
1083 :
1084 0 : for( int iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
1085 : {
1086 0 : fprintf( stderr, " -> %s\n", poR->GetDriver(iDriver)->GetName() );
1087 : }
1088 :
1089 0 : exit( 1 );
1090 : }
1091 :
1092 : /* -------------------------------------------------------------------- */
1093 : /* Try opening the output datasource as an existing, writable */
1094 : /* -------------------------------------------------------------------- */
1095 62 : OGRDataSource *poODS = NULL;
1096 62 : OGRSFDriver *poDriver = NULL;
1097 62 : int bCloseODS = TRUE;
1098 :
1099 62 : if( bUpdate )
1100 : {
1101 : /* Special case for FileGDB that doesn't like updating if the same */
1102 : /* GDB is opened twice. It stalls at datasource closing. So use just */
1103 : /* one single connection. This could also TRUE for other drivers. */
1104 17 : if (EQUAL(poDS->GetDriver()->GetName(), "FileGDB") &&
1105 : strcmp(pszDestDataSource, pszDataSource) == 0)
1106 : {
1107 0 : poODS = poDS;
1108 0 : poDriver = poODS->GetDriver();
1109 0 : bCloseODS = FALSE;
1110 0 : if (bOverwrite || bAppend)
1111 : {
1112 : /* Various tests to avoid overwriting the source layer(s) */
1113 : /* or to avoid appending a layer to itself */
1114 0 : int bError = FALSE;
1115 0 : if (pszNewLayerName == NULL)
1116 0 : bError = TRUE;
1117 0 : else if (CSLCount(papszLayers) == 1)
1118 0 : bError = strcmp(pszNewLayerName, papszLayers[0]) == 0;
1119 0 : else if (pszSQLStatement == NULL)
1120 0 : bError = TRUE;
1121 0 : if (bError)
1122 : {
1123 : fprintf( stderr,
1124 : "ERROR: -nln name must be specified combined with "
1125 : "a single source layer name,\nor a -sql statement, and "
1126 0 : "name must be different from an existing layer.\n");
1127 0 : exit(1);
1128 : }
1129 : }
1130 : }
1131 : else
1132 17 : poODS = OGRSFDriverRegistrar::Open( pszDestDataSource, TRUE, &poDriver );
1133 :
1134 17 : if( poODS == NULL )
1135 : {
1136 1 : if (bOverwrite || bAppend)
1137 : {
1138 1 : poODS = OGRSFDriverRegistrar::Open( pszDestDataSource, FALSE, &poDriver );
1139 1 : if (poODS == NULL)
1140 : {
1141 : /* ok the datasource doesn't exist at all */
1142 1 : bUpdate = FALSE;
1143 : }
1144 : else
1145 : {
1146 0 : OGRDataSource::DestroyDataSource(poODS);
1147 0 : poODS = NULL;
1148 : }
1149 : }
1150 :
1151 1 : if (bUpdate)
1152 : {
1153 : fprintf( stderr, "FAILURE:\n"
1154 : "Unable to open existing output datasource `%s'.\n",
1155 0 : pszDestDataSource );
1156 0 : exit( 1 );
1157 : }
1158 : }
1159 16 : else if( CSLCount(papszDSCO) > 0 )
1160 : {
1161 : fprintf( stderr, "WARNING: Datasource creation options ignored since an existing datasource\n"
1162 0 : " being updated.\n" );
1163 : }
1164 : }
1165 :
1166 : /* -------------------------------------------------------------------- */
1167 : /* Find the output driver. */
1168 : /* -------------------------------------------------------------------- */
1169 62 : if( !bUpdate )
1170 : {
1171 46 : if (!bQuiet && !bFormatExplicitelySet)
1172 35 : CheckDestDataSourceNameConsistency(pszDestDataSource, pszFormat);
1173 :
1174 46 : OGRSFDriverRegistrar *poR = OGRSFDriverRegistrar::GetRegistrar();
1175 : int iDriver;
1176 :
1177 46 : poDriver = poR->GetDriverByName(pszFormat);
1178 46 : if( poDriver == NULL )
1179 : {
1180 0 : fprintf( stderr, "Unable to find driver `%s'.\n", pszFormat );
1181 0 : fprintf( stderr, "The following drivers are available:\n" );
1182 :
1183 0 : for( iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
1184 : {
1185 0 : fprintf( stderr, " -> `%s'\n", poR->GetDriver(iDriver)->GetName() );
1186 : }
1187 0 : exit( 1 );
1188 : }
1189 :
1190 46 : if( !poDriver->TestCapability( ODrCCreateDataSource ) )
1191 : {
1192 : fprintf( stderr, "%s driver does not support data source creation.\n",
1193 0 : pszFormat );
1194 0 : exit( 1 );
1195 : }
1196 :
1197 : /* -------------------------------------------------------------------- */
1198 : /* Special case to improve user experience when translating */
1199 : /* a datasource with multiple layers into a shapefile. If the */
1200 : /* user gives a target datasource with .shp and it does not exist, */
1201 : /* the shapefile driver will try to create a file, but this is not */
1202 : /* appropriate because here we have several layers, so create */
1203 : /* a directory instead. */
1204 : /* -------------------------------------------------------------------- */
1205 : VSIStatBufL sStat;
1206 77 : if (EQUAL(poDriver->GetName(), "ESRI Shapefile") &&
1207 : pszSQLStatement == NULL &&
1208 : (CSLCount(papszLayers) > 1 ||
1209 31 : (CSLCount(papszLayers) == 0 && poDS->GetLayerCount() > 1)) &&
1210 : pszNewLayerName == NULL &&
1211 : EQUAL(CPLGetExtension(pszDestDataSource), "SHP") &&
1212 : VSIStatL(pszDestDataSource, &sStat) != 0)
1213 : {
1214 1 : if (VSIMkdir(pszDestDataSource, 0755) != 0)
1215 : {
1216 : CPLError( CE_Failure, CPLE_AppDefined,
1217 : "Failed to create directory %s\n"
1218 : "for shapefile datastore.\n",
1219 0 : pszDestDataSource );
1220 0 : exit(1);
1221 : }
1222 : }
1223 :
1224 : /* -------------------------------------------------------------------- */
1225 : /* Create the output data source. */
1226 : /* -------------------------------------------------------------------- */
1227 46 : poODS = poDriver->CreateDataSource( pszDestDataSource, papszDSCO );
1228 46 : if( poODS == NULL )
1229 : {
1230 : fprintf( stderr, "%s driver failed to create %s\n",
1231 0 : pszFormat, pszDestDataSource );
1232 0 : exit( 1 );
1233 : }
1234 : }
1235 :
1236 : /* -------------------------------------------------------------------- */
1237 : /* Parse the output SRS definition if possible. */
1238 : /* -------------------------------------------------------------------- */
1239 62 : if( pszOutputSRSDef != NULL )
1240 : {
1241 3 : poOutputSRS = (OGRSpatialReference*)OSRNewSpatialReference(NULL);
1242 3 : if( poOutputSRS->SetFromUserInput( pszOutputSRSDef ) != OGRERR_NONE )
1243 : {
1244 : fprintf( stderr, "Failed to process SRS definition: %s\n",
1245 0 : pszOutputSRSDef );
1246 0 : exit( 1 );
1247 : }
1248 : }
1249 :
1250 : /* -------------------------------------------------------------------- */
1251 : /* Parse the source SRS definition if possible. */
1252 : /* -------------------------------------------------------------------- */
1253 62 : if( pszSourceSRSDef != NULL )
1254 : {
1255 0 : poSourceSRS = (OGRSpatialReference*)OSRNewSpatialReference(NULL);
1256 0 : if( poSourceSRS->SetFromUserInput( pszSourceSRSDef ) != OGRERR_NONE )
1257 : {
1258 : fprintf( stderr, "Failed to process SRS definition: %s\n",
1259 0 : pszSourceSRSDef );
1260 0 : exit( 1 );
1261 : }
1262 : }
1263 :
1264 : /* -------------------------------------------------------------------- */
1265 : /* Special case for -sql clause. No source layers required. */
1266 : /* -------------------------------------------------------------------- */
1267 62 : if( pszSQLStatement != NULL )
1268 : {
1269 : OGRLayer *poResultSet;
1270 :
1271 6 : if( pszWHERE != NULL )
1272 0 : fprintf( stderr, "-where clause ignored in combination with -sql.\n" );
1273 6 : if( CSLCount(papszLayers) > 0 )
1274 0 : fprintf( stderr, "layer names ignored in combination with -sql.\n" );
1275 :
1276 : poResultSet = poDS->ExecuteSQL( pszSQLStatement, poSpatialFilter,
1277 6 : pszDialect );
1278 :
1279 6 : if( poResultSet != NULL )
1280 : {
1281 6 : long nCountLayerFeatures = 0;
1282 6 : if (bDisplayProgress)
1283 : {
1284 0 : if (!poResultSet->TestCapability(OLCFastFeatureCount))
1285 : {
1286 0 : fprintf( stderr, "Progress turned off as fast feature count is not available.\n");
1287 0 : bDisplayProgress = FALSE;
1288 : }
1289 : else
1290 : {
1291 0 : nCountLayerFeatures = poResultSet->GetFeatureCount();
1292 0 : pfnProgress = GDALTermProgress;
1293 : }
1294 : }
1295 :
1296 6 : OGRLayer* poPassedLayer = poResultSet;
1297 6 : if (bSplitListFields)
1298 : {
1299 0 : poPassedLayer = new OGRSplitListFieldLayer(poPassedLayer, nMaxSplitListSubFields);
1300 0 : int nRet = ((OGRSplitListFieldLayer*)poPassedLayer)->BuildLayerDefn(NULL, NULL);
1301 0 : if (!nRet)
1302 : {
1303 0 : delete poPassedLayer;
1304 0 : poPassedLayer = poResultSet;
1305 : }
1306 : }
1307 :
1308 : /* -------------------------------------------------------------------- */
1309 : /* Special case to improve user experience when translating into */
1310 : /* single file shapefile and source has only one layer, and that */
1311 : /* the layer name isn't specified */
1312 : /* -------------------------------------------------------------------- */
1313 : VSIStatBufL sStat;
1314 6 : if (EQUAL(poDriver->GetName(), "ESRI Shapefile") &&
1315 : pszNewLayerName == NULL &&
1316 : VSIStatL(pszDestDataSource, &sStat) == 0 && VSI_ISREG(sStat.st_mode))
1317 : {
1318 0 : pszNewLayerName = CPLStrdup(CPLGetBasename(pszDestDataSource));
1319 : }
1320 :
1321 6 : if( !TranslateLayer( poDS, poPassedLayer, poODS, papszLCO,
1322 : pszNewLayerName, bTransform, poOutputSRS, bNullifyOutputSRS,
1323 : poSourceSRS, papszSelFields, bAppend, eGType,
1324 : bOverwrite, eGeomOp, dfGeomOpParam, papszFieldTypesToString,
1325 : nCountLayerFeatures, bWrapDateline, poClipSrc, poClipDst,
1326 : bExplodeCollections, pszZField, pszWHERE, pfnProgress, pProgressArg))
1327 : {
1328 : CPLError( CE_Failure, CPLE_AppDefined,
1329 : "Terminating translation prematurely after failed\n"
1330 0 : "translation from sql statement." );
1331 :
1332 0 : exit( 1 );
1333 : }
1334 :
1335 6 : if (poPassedLayer != poResultSet)
1336 0 : delete poPassedLayer;
1337 :
1338 6 : poDS->ReleaseResultSet( poResultSet );
1339 : }
1340 : }
1341 :
1342 : else
1343 : {
1344 56 : int nLayerCount = 0;
1345 56 : OGRLayer** papoLayers = NULL;
1346 :
1347 : /* -------------------------------------------------------------------- */
1348 : /* Process each data source layer. */
1349 : /* -------------------------------------------------------------------- */
1350 56 : if ( CSLCount(papszLayers) == 0)
1351 : {
1352 53 : nLayerCount = poDS->GetLayerCount();
1353 53 : papoLayers = (OGRLayer**)CPLMalloc(sizeof(OGRLayer*) * nLayerCount);
1354 :
1355 124 : for( int iLayer = 0;
1356 : iLayer < nLayerCount;
1357 : iLayer++ )
1358 : {
1359 71 : OGRLayer *poLayer = poDS->GetLayer(iLayer);
1360 :
1361 71 : if( poLayer == NULL )
1362 : {
1363 : fprintf( stderr, "FAILURE: Couldn't fetch advertised layer %d!\n",
1364 0 : iLayer );
1365 0 : exit( 1 );
1366 : }
1367 :
1368 71 : papoLayers[iLayer] = poLayer;
1369 : }
1370 : }
1371 : /* -------------------------------------------------------------------- */
1372 : /* Process specified data source layers. */
1373 : /* -------------------------------------------------------------------- */
1374 : else
1375 : {
1376 3 : nLayerCount = CSLCount(papszLayers);
1377 3 : papoLayers = (OGRLayer**)CPLMalloc(sizeof(OGRLayer*) * nLayerCount);
1378 :
1379 12 : for( int iLayer = 0;
1380 6 : papszLayers[iLayer] != NULL;
1381 : iLayer++ )
1382 : {
1383 3 : OGRLayer *poLayer = poDS->GetLayerByName(papszLayers[iLayer]);
1384 :
1385 3 : if( poLayer == NULL )
1386 : {
1387 : fprintf( stderr, "FAILURE: Couldn't fetch requested layer '%s'!\n",
1388 0 : papszLayers[iLayer] );
1389 0 : if (!bSkipFailures)
1390 0 : exit( 1 );
1391 : }
1392 :
1393 3 : papoLayers[iLayer] = poLayer;
1394 : }
1395 : }
1396 :
1397 : /* -------------------------------------------------------------------- */
1398 : /* Special case to improve user experience when translating into */
1399 : /* single file shapefile and source has only one layer, and that */
1400 : /* the layer name isn't specified */
1401 : /* -------------------------------------------------------------------- */
1402 : VSIStatBufL sStat;
1403 56 : if (EQUAL(poDriver->GetName(), "ESRI Shapefile") &&
1404 : nLayerCount == 1 && pszNewLayerName == NULL &&
1405 : VSIStatL(pszDestDataSource, &sStat) == 0 && VSI_ISREG(sStat.st_mode))
1406 : {
1407 3 : pszNewLayerName = CPLStrdup(CPLGetBasename(pszDestDataSource));
1408 : }
1409 :
1410 56 : long* panLayerCountFeatures = (long*) CPLMalloc(sizeof(long) * nLayerCount);
1411 56 : long nCountLayersFeatures = 0;
1412 56 : long nAccCountFeatures = 0;
1413 : int iLayer;
1414 :
1415 : /* First pass to apply filters and count all features if necessary */
1416 130 : for( iLayer = 0;
1417 : iLayer < nLayerCount;
1418 : iLayer++ )
1419 : {
1420 74 : OGRLayer *poLayer = papoLayers[iLayer];
1421 74 : if (poLayer == NULL)
1422 0 : continue;
1423 :
1424 74 : if( pszWHERE != NULL )
1425 : {
1426 2 : if( poLayer->SetAttributeFilter( pszWHERE ) != OGRERR_NONE )
1427 : {
1428 0 : fprintf( stderr, "FAILURE: SetAttributeFilter(%s) failed.\n", pszWHERE );
1429 0 : if (!bSkipFailures)
1430 0 : exit( 1 );
1431 : }
1432 : }
1433 :
1434 74 : if( poSpatialFilter != NULL )
1435 2 : poLayer->SetSpatialFilter( poSpatialFilter );
1436 :
1437 74 : if (bDisplayProgress)
1438 : {
1439 1 : if (!poLayer->TestCapability(OLCFastFeatureCount))
1440 : {
1441 0 : fprintf( stderr, "Progress turned off as fast feature count is not available.\n");
1442 0 : bDisplayProgress = FALSE;
1443 : }
1444 : else
1445 : {
1446 1 : panLayerCountFeatures[iLayer] = poLayer->GetFeatureCount();
1447 1 : nCountLayersFeatures += panLayerCountFeatures[iLayer];
1448 : }
1449 : }
1450 : }
1451 :
1452 : /* Second pass to do the real job */
1453 130 : for( iLayer = 0;
1454 : iLayer < nLayerCount;
1455 : iLayer++ )
1456 : {
1457 74 : OGRLayer *poLayer = papoLayers[iLayer];
1458 74 : if (poLayer == NULL)
1459 0 : continue;
1460 :
1461 :
1462 74 : OGRLayer* poPassedLayer = poLayer;
1463 74 : if (bSplitListFields)
1464 : {
1465 1 : poPassedLayer = new OGRSplitListFieldLayer(poPassedLayer, nMaxSplitListSubFields);
1466 :
1467 1 : if (bDisplayProgress && nMaxSplitListSubFields != 1)
1468 : {
1469 0 : pfnProgress = GDALScaledProgress;
1470 : pProgressArg =
1471 : GDALCreateScaledProgress(nAccCountFeatures * 1.0 / nCountLayersFeatures,
1472 0 : (nAccCountFeatures + panLayerCountFeatures[iLayer] / 2) * 1.0 / nCountLayersFeatures,
1473 : GDALTermProgress,
1474 0 : NULL);
1475 : }
1476 : else
1477 : {
1478 1 : pfnProgress = NULL;
1479 1 : pProgressArg = NULL;
1480 : }
1481 :
1482 1 : int nRet = ((OGRSplitListFieldLayer*)poPassedLayer)->BuildLayerDefn(pfnProgress, pProgressArg);
1483 1 : if (!nRet)
1484 : {
1485 0 : delete poPassedLayer;
1486 0 : poPassedLayer = poLayer;
1487 : }
1488 :
1489 1 : if (bDisplayProgress)
1490 0 : GDALDestroyScaledProgress(pProgressArg);
1491 : }
1492 :
1493 :
1494 74 : if (bDisplayProgress)
1495 : {
1496 1 : pfnProgress = GDALScaledProgress;
1497 1 : int nStart = 0;
1498 1 : if (poPassedLayer != poLayer && nMaxSplitListSubFields != 1)
1499 0 : nStart = panLayerCountFeatures[iLayer] / 2;
1500 : pProgressArg =
1501 : GDALCreateScaledProgress((nAccCountFeatures + nStart) * 1.0 / nCountLayersFeatures,
1502 1 : (nAccCountFeatures + panLayerCountFeatures[iLayer]) * 1.0 / nCountLayersFeatures,
1503 : GDALTermProgress,
1504 1 : NULL);
1505 : }
1506 :
1507 74 : nAccCountFeatures += panLayerCountFeatures[iLayer];
1508 :
1509 74 : if( !TranslateLayer( poDS, poPassedLayer, poODS, papszLCO,
1510 : pszNewLayerName, bTransform, poOutputSRS, bNullifyOutputSRS,
1511 : poSourceSRS, papszSelFields, bAppend, eGType,
1512 : bOverwrite, eGeomOp, dfGeomOpParam, papszFieldTypesToString,
1513 : panLayerCountFeatures[iLayer], bWrapDateline, poClipSrc, poClipDst,
1514 : bExplodeCollections, pszZField, pszWHERE, pfnProgress, pProgressArg)
1515 : && !bSkipFailures )
1516 : {
1517 : CPLError( CE_Failure, CPLE_AppDefined,
1518 : "Terminating translation prematurely after failed\n"
1519 : "translation of layer %s (use -skipfailures to skip errors)\n",
1520 0 : poLayer->GetName() );
1521 :
1522 0 : exit( 1 );
1523 : }
1524 :
1525 74 : if (poPassedLayer != poLayer)
1526 1 : delete poPassedLayer;
1527 :
1528 74 : if (bDisplayProgress)
1529 1 : GDALDestroyScaledProgress(pProgressArg);
1530 : }
1531 :
1532 56 : CPLFree(panLayerCountFeatures);
1533 56 : CPLFree(papoLayers);
1534 : }
1535 : /* -------------------------------------------------------------------- */
1536 : /* Process DS style table */
1537 : /* -------------------------------------------------------------------- */
1538 :
1539 62 : poODS->SetStyleTable( poDS->GetStyleTable () );
1540 :
1541 : /* -------------------------------------------------------------------- */
1542 : /* Close down. */
1543 : /* -------------------------------------------------------------------- */
1544 62 : OGRSpatialReference::DestroySpatialReference(poOutputSRS);
1545 62 : OGRSpatialReference::DestroySpatialReference(poSourceSRS);
1546 62 : if (bCloseODS)
1547 62 : OGRDataSource::DestroyDataSource(poODS);
1548 62 : OGRDataSource::DestroyDataSource(poDS);
1549 62 : OGRGeometryFactory::destroyGeometry(poSpatialFilter);
1550 62 : OGRGeometryFactory::destroyGeometry(poClipSrc);
1551 62 : OGRGeometryFactory::destroyGeometry(poClipDst);
1552 :
1553 62 : CSLDestroy(papszSelFields);
1554 62 : CSLDestroy( papszArgv );
1555 62 : CSLDestroy( papszLayers );
1556 62 : CSLDestroy( papszDSCO );
1557 62 : CSLDestroy( papszLCO );
1558 62 : CSLDestroy( papszFieldTypesToString );
1559 62 : CPLFree( pszNewLayerName );
1560 :
1561 62 : OGRCleanupAll();
1562 :
1563 : #ifdef DBMALLOC
1564 : malloc_dump(1);
1565 : #endif
1566 :
1567 62 : return 0;
1568 : }
1569 :
1570 : /************************************************************************/
1571 : /* Usage() */
1572 : /************************************************************************/
1573 :
1574 0 : static void Usage(int bShort)
1575 :
1576 : {
1577 0 : OGRSFDriverRegistrar *poR = OGRSFDriverRegistrar::GetRegistrar();
1578 :
1579 :
1580 : printf( "Usage: ogr2ogr [--help-general] [-skipfailures] [-append] [-update]\n"
1581 : " [-select field_list] [-where restricted_where]\n"
1582 : " [-progress] [-sql <sql statement>] [-dialect dialect]\n"
1583 : " [-preserve_fid] [-fid FID]\n"
1584 : " [-spat xmin ymin xmax ymax]\n"
1585 : " [-a_srs srs_def] [-t_srs srs_def] [-s_srs srs_def]\n"
1586 : " [-f format_name] [-overwrite] [[-dsco NAME=VALUE] ...]\n"
1587 : " dst_datasource_name src_datasource_name\n"
1588 : " [-lco NAME=VALUE] [-nln name] [-nlt type] [layer [layer ...]]\n"
1589 : "\n"
1590 : "Advanced options :\n"
1591 : " [-gt n]\n"
1592 : " [-clipsrc [xmin ymin xmax ymax]|WKT|datasource|spat_extent]\n"
1593 : " [-clipsrcsql sql_statement] [-clipsrclayer layer]\n"
1594 : " [-clipsrcwhere expression]\n"
1595 : " [-clipdst [xmin ymin xmax ymax]|WKT|datasource]\n"
1596 : " [-clipdstsql sql_statement] [-clipdstlayer layer]\n"
1597 : " [-clipdstwhere expression]\n"
1598 : " [-wrapdateline]\n"
1599 : " [[-simplify tolerance] | [-segmentize max_dist]]\n"
1600 : " [-fieldTypeToString All|(type1[,type2]*)]\n"
1601 : " [-splitlistfields] [-maxsubfields val]\n"
1602 0 : " [-explodecollections] [-zfield field_name]\n");
1603 :
1604 0 : if (bShort)
1605 : {
1606 0 : printf( "\nNote: ogr2ogr --long-usage for full help.\n");
1607 0 : exit( 1 );
1608 : }
1609 :
1610 0 : printf("\n -f format_name: output file format name, possible values are:\n");
1611 :
1612 0 : for( int iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
1613 : {
1614 0 : OGRSFDriver *poDriver = poR->GetDriver(iDriver);
1615 :
1616 0 : if( poDriver->TestCapability( ODrCCreateDataSource ) )
1617 0 : printf( " -f \"%s\"\n", poDriver->GetName() );
1618 : }
1619 :
1620 : printf( " -append: Append to existing layer instead of creating new if it exists\n"
1621 : " -overwrite: delete the output layer and recreate it empty\n"
1622 : " -update: Open existing output datasource in update mode\n"
1623 : " -progress: Display progress on terminal. Only works if input layers have the \n"
1624 : " \"fast feature count\" capability\n"
1625 : " -select field_list: Comma-delimited list of fields from input layer to\n"
1626 : " copy to the new layer (defaults to all)\n"
1627 : " -where restricted_where: Attribute query (like SQL WHERE)\n"
1628 : " -wrapdateline: split geometries crossing the dateline meridian\n"
1629 : " (long. = +/- 180deg)\n"
1630 : " -sql statement: Execute given SQL statement and save result.\n"
1631 : " -dialect value: select a dialect, usually OGRSQL to avoid native sql.\n"
1632 : " -skipfailures: skip features or layers that fail to convert\n"
1633 : " -gt n: group n features per transaction (default 200)\n"
1634 : " -spat xmin ymin xmax ymax: spatial query extents\n"
1635 : " -simplify tolerance: distance tolerance for simplification.\n"
1636 : " -segmentize max_dist: maximum distance between 2 nodes.\n"
1637 : " Used to create intermediate points\n"
1638 : " -dsco NAME=VALUE: Dataset creation option (format specific)\n"
1639 : " -lco NAME=VALUE: Layer creation option (format specific)\n"
1640 : " -nln name: Assign an alternate name to the new layer\n"
1641 : " -nlt type: Force a geometry type for new layer. One of NONE, GEOMETRY,\n"
1642 : " POINT, LINESTRING, POLYGON, GEOMETRYCOLLECTION, MULTIPOINT,\n"
1643 : " MULTIPOLYGON, or MULTILINESTRING. Add \"25D\" for 3D layers.\n"
1644 : " Default is type of source layer.\n"
1645 : " -fieldTypeToString type1,...: Converts fields of specified types to\n"
1646 : " fields of type string in the new layer. Valid types are : Integer,\n"
1647 : " Real, String, Date, Time, DateTime, Binary, IntegerList, RealList,\n"
1648 0 : " StringList. Special value All will convert all fields to strings.\n");
1649 :
1650 : printf(" -a_srs srs_def: Assign an output SRS\n"
1651 : " -t_srs srs_def: Reproject/transform to this SRS on output\n"
1652 : " -s_srs srs_def: Override source SRS\n"
1653 : "\n"
1654 : " Srs_def can be a full WKT definition (hard to escape properly),\n"
1655 : " or a well known definition (ie. EPSG:4326) or a file with a WKT\n"
1656 0 : " definition.\n" );
1657 :
1658 0 : exit( 1 );
1659 : }
1660 :
1661 : /************************************************************************/
1662 : /* SetZ() */
1663 : /************************************************************************/
1664 60 : static void SetZ (OGRGeometry* poGeom, double dfZ )
1665 : {
1666 60 : if (poGeom == NULL)
1667 0 : return;
1668 60 : switch (wkbFlatten(poGeom->getGeometryType()))
1669 : {
1670 : case wkbPoint:
1671 0 : ((OGRPoint*)poGeom)->setZ(dfZ);
1672 0 : break;
1673 :
1674 : case wkbLineString:
1675 : case wkbLinearRing:
1676 : {
1677 : int i;
1678 30 : OGRLineString* poLS = (OGRLineString*) poGeom;
1679 765 : for(i=0;i<poLS->getNumPoints();i++)
1680 735 : poLS->setPoint(i, poLS->getX(i), poLS->getY(i), dfZ);
1681 30 : break;
1682 : }
1683 :
1684 : case wkbPolygon:
1685 : {
1686 : int i;
1687 30 : OGRPolygon* poPoly = (OGRPolygon*) poGeom;
1688 30 : SetZ(poPoly->getExteriorRing(), dfZ);
1689 30 : for(i=0;i<poPoly->getNumInteriorRings();i++)
1690 0 : SetZ(poPoly->getInteriorRing(i), dfZ);
1691 30 : break;
1692 : }
1693 :
1694 : case wkbMultiPoint:
1695 : case wkbMultiLineString:
1696 : case wkbMultiPolygon:
1697 : case wkbGeometryCollection:
1698 : {
1699 : int i;
1700 0 : OGRGeometryCollection* poGeomColl = (OGRGeometryCollection*) poGeom;
1701 0 : for(i=0;i<poGeomColl->getNumGeometries();i++)
1702 0 : SetZ(poGeomColl->getGeometryRef(i), dfZ);
1703 : break;
1704 : }
1705 :
1706 : default:
1707 : break;
1708 : }
1709 : }
1710 :
1711 :
1712 : /************************************************************************/
1713 : /* TranslateLayer() */
1714 : /************************************************************************/
1715 :
1716 80 : static int TranslateLayer( OGRDataSource *poSrcDS,
1717 : OGRLayer * poSrcLayer,
1718 : OGRDataSource *poDstDS,
1719 : char **papszLCO,
1720 : const char *pszNewLayerName,
1721 : int bTransform,
1722 : OGRSpatialReference *poOutputSRS,
1723 : int bNullifyOutputSRS,
1724 : OGRSpatialReference *poSourceSRS,
1725 : char **papszSelFields,
1726 : int bAppend, int eGType, int bOverwrite,
1727 : GeomOperation eGeomOp,
1728 : double dfGeomOpParam,
1729 : char** papszFieldTypesToString,
1730 : long nCountLayerFeatures,
1731 : int bWrapDateline,
1732 : OGRGeometry* poClipSrc,
1733 : OGRGeometry *poClipDst,
1734 : int bExplodeCollections,
1735 : const char* pszZField,
1736 : const char* pszWHERE,
1737 : GDALProgressFunc pfnProgress,
1738 : void *pProgressArg)
1739 :
1740 : {
1741 : OGRLayer *poDstLayer;
1742 : OGRFeatureDefn *poSrcFDefn;
1743 80 : OGRFeatureDefn *poDstFDefn = NULL;
1744 80 : int bForceToPolygon = FALSE;
1745 80 : int bForceToMultiPolygon = FALSE;
1746 80 : int bForceToMultiLineString = FALSE;
1747 :
1748 80 : char** papszTransformOptions = NULL;
1749 :
1750 80 : if( pszNewLayerName == NULL )
1751 66 : pszNewLayerName = poSrcLayer->GetName();
1752 :
1753 80 : if( wkbFlatten(eGType) == wkbPolygon )
1754 1 : bForceToPolygon = TRUE;
1755 79 : else if( wkbFlatten(eGType) == wkbMultiPolygon )
1756 2 : bForceToMultiPolygon = TRUE;
1757 77 : else if( wkbFlatten(eGType) == wkbMultiLineString )
1758 0 : bForceToMultiLineString = TRUE;
1759 :
1760 : /* -------------------------------------------------------------------- */
1761 : /* Setup coordinate transformation if we need it. */
1762 : /* -------------------------------------------------------------------- */
1763 80 : OGRCoordinateTransformation *poCT = NULL;
1764 :
1765 80 : if( bTransform )
1766 : {
1767 2 : if( poSourceSRS == NULL )
1768 2 : poSourceSRS = poSrcLayer->GetSpatialRef();
1769 :
1770 2 : if( poSourceSRS == NULL )
1771 : {
1772 : fprintf( stderr, "Can't transform coordinates, source layer has no\n"
1773 0 : "coordinate system. Use -s_srs to set one.\n" );
1774 0 : exit( 1 );
1775 : }
1776 :
1777 2 : CPLAssert( NULL != poSourceSRS );
1778 2 : CPLAssert( NULL != poOutputSRS );
1779 :
1780 2 : poCT = OGRCreateCoordinateTransformation( poSourceSRS, poOutputSRS );
1781 2 : if( poCT == NULL )
1782 : {
1783 0 : char *pszWKT = NULL;
1784 :
1785 : fprintf( stderr, "Failed to create coordinate transformation between the\n"
1786 : "following coordinate systems. This may be because they\n"
1787 : "are not transformable, or because projection services\n"
1788 0 : "(PROJ.4 DLL/.so) could not be loaded.\n" );
1789 :
1790 0 : poSourceSRS->exportToPrettyWkt( &pszWKT, FALSE );
1791 0 : fprintf( stderr, "Source:\n%s\n", pszWKT );
1792 :
1793 0 : poOutputSRS->exportToPrettyWkt( &pszWKT, FALSE );
1794 0 : fprintf( stderr, "Target:\n%s\n", pszWKT );
1795 0 : exit( 1 );
1796 : }
1797 : }
1798 :
1799 80 : if (bWrapDateline)
1800 : {
1801 4 : if( poSourceSRS == NULL )
1802 3 : poSourceSRS = poSrcLayer->GetSpatialRef();
1803 :
1804 4 : if (poCT != NULL && poOutputSRS->IsGeographic())
1805 : {
1806 : papszTransformOptions =
1807 1 : CSLAddString(papszTransformOptions, "WRAPDATELINE=YES");
1808 : }
1809 3 : else if (poSourceSRS != NULL && poOutputSRS == NULL && poSourceSRS->IsGeographic())
1810 : {
1811 : papszTransformOptions =
1812 3 : CSLAddString(papszTransformOptions, "WRAPDATELINE=YES");
1813 : }
1814 : else
1815 : {
1816 0 : fprintf(stderr, "-wrapdateline option only works when reprojecting to a geographic SRS\n");
1817 : }
1818 : }
1819 :
1820 : /* -------------------------------------------------------------------- */
1821 : /* Get other info. */
1822 : /* -------------------------------------------------------------------- */
1823 80 : poSrcFDefn = poSrcLayer->GetLayerDefn();
1824 :
1825 80 : if( poOutputSRS == NULL && !bNullifyOutputSRS )
1826 76 : poOutputSRS = poSrcLayer->GetSpatialRef();
1827 :
1828 : /* -------------------------------------------------------------------- */
1829 : /* Find the layer. */
1830 : /* -------------------------------------------------------------------- */
1831 :
1832 : /* GetLayerByName() can instanciate layers that would have been */
1833 : /* 'hidden' otherwise, for example, non-spatial tables in a */
1834 : /* Postgis-enabled database, so this apparently useless command is */
1835 : /* not useless... (#4012) */
1836 80 : CPLPushErrorHandler(CPLQuietErrorHandler);
1837 80 : poDstLayer = poDstDS->GetLayerByName(pszNewLayerName);
1838 80 : CPLPopErrorHandler();
1839 80 : CPLErrorReset();
1840 :
1841 80 : int iLayer = -1;
1842 80 : if (poDstLayer != NULL)
1843 : {
1844 13 : int nLayerCount = poDstDS->GetLayerCount();
1845 252 : for( iLayer = 0; iLayer < nLayerCount; iLayer++ )
1846 : {
1847 252 : OGRLayer *poLayer = poDstDS->GetLayer(iLayer);
1848 252 : if (poLayer == poDstLayer)
1849 13 : break;
1850 : }
1851 :
1852 13 : if (iLayer == nLayerCount)
1853 : /* shouldn't happen with an ideal driver */
1854 0 : poDstLayer = NULL;
1855 : }
1856 :
1857 : /* -------------------------------------------------------------------- */
1858 : /* If the user requested overwrite, and we have the layer in */
1859 : /* question we need to delete it now so it will get recreated */
1860 : /* (overwritten). */
1861 : /* -------------------------------------------------------------------- */
1862 80 : if( poDstLayer != NULL && bOverwrite )
1863 : {
1864 7 : if( poDstDS->DeleteLayer( iLayer ) != OGRERR_NONE )
1865 : {
1866 : fprintf( stderr,
1867 0 : "DeleteLayer() failed when overwrite requested.\n" );
1868 0 : CSLDestroy(papszTransformOptions);
1869 0 : return FALSE;
1870 : }
1871 7 : poDstLayer = NULL;
1872 : }
1873 :
1874 : /* -------------------------------------------------------------------- */
1875 : /* If the layer does not exist, then create it. */
1876 : /* -------------------------------------------------------------------- */
1877 80 : if( poDstLayer == NULL )
1878 : {
1879 74 : if( eGType == -2 )
1880 : {
1881 67 : eGType = poSrcFDefn->GetGeomType();
1882 :
1883 67 : if ( bExplodeCollections )
1884 : {
1885 1 : int n25DBit = eGType & wkb25DBit;
1886 1 : if (wkbFlatten(eGType) == wkbMultiPoint)
1887 : {
1888 0 : eGType = wkbPoint | n25DBit;
1889 : }
1890 1 : else if (wkbFlatten(eGType) == wkbMultiLineString)
1891 : {
1892 0 : eGType = wkbLineString | n25DBit;
1893 : }
1894 1 : else if (wkbFlatten(eGType) == wkbMultiPolygon)
1895 : {
1896 0 : eGType = wkbPolygon | n25DBit;
1897 : }
1898 1 : else if (wkbFlatten(eGType) == wkbGeometryCollection)
1899 : {
1900 0 : eGType = wkbUnknown | n25DBit;
1901 : }
1902 : }
1903 :
1904 67 : if ( pszZField )
1905 3 : eGType |= wkb25DBit;
1906 : }
1907 :
1908 74 : if( !poDstDS->TestCapability( ODsCCreateLayer ) )
1909 : {
1910 : fprintf( stderr,
1911 : "Layer %s not found, and CreateLayer not supported by driver.",
1912 0 : pszNewLayerName );
1913 0 : return FALSE;
1914 : }
1915 :
1916 74 : CPLErrorReset();
1917 :
1918 : poDstLayer = poDstDS->CreateLayer( pszNewLayerName, poOutputSRS,
1919 : (OGRwkbGeometryType) eGType,
1920 74 : papszLCO );
1921 :
1922 74 : if( poDstLayer == NULL )
1923 : {
1924 0 : CSLDestroy(papszTransformOptions);
1925 0 : return FALSE;
1926 : }
1927 :
1928 74 : bAppend = FALSE;
1929 : }
1930 :
1931 : /* -------------------------------------------------------------------- */
1932 : /* Otherwise we will append to it, if append was requested. */
1933 : /* -------------------------------------------------------------------- */
1934 6 : else if( !bAppend )
1935 : {
1936 : fprintf( stderr, "FAILED: Layer %s already exists, and -append not specified.\n"
1937 : " Consider using -append, or -overwrite.\n",
1938 0 : pszNewLayerName );
1939 0 : return FALSE;
1940 : }
1941 : else
1942 : {
1943 6 : if( CSLCount(papszLCO) > 0 )
1944 : {
1945 : fprintf( stderr, "WARNING: Layer creation options ignored since an existing layer is\n"
1946 0 : " being appended to.\n" );
1947 : }
1948 : }
1949 :
1950 : /* -------------------------------------------------------------------- */
1951 : /* Process Layer style table */
1952 : /* -------------------------------------------------------------------- */
1953 :
1954 80 : poDstLayer->SetStyleTable( poSrcLayer->GetStyleTable () );
1955 : /* -------------------------------------------------------------------- */
1956 : /* Add fields. Default to copy all field. */
1957 : /* If only a subset of all fields requested, then output only */
1958 : /* the selected fields, and in the order that they were */
1959 : /* selected. */
1960 : /* -------------------------------------------------------------------- */
1961 80 : int nSrcFieldCount = poSrcFDefn->GetFieldCount();
1962 : int iField, *panMap;
1963 :
1964 : // Initialize the index-to-index map to -1's
1965 80 : panMap = (int *) VSIMalloc( sizeof(int) * nSrcFieldCount );
1966 547 : for( iField=0; iField < nSrcFieldCount; iField++)
1967 467 : panMap[iField] = -1;
1968 :
1969 : /* Caution : at the time of writing, the MapInfo driver */
1970 : /* returns NULL until a field has been added */
1971 80 : poDstFDefn = poDstLayer->GetLayerDefn();
1972 :
1973 86 : if (papszSelFields && !bAppend )
1974 : {
1975 6 : int nDstFieldCount = 0;
1976 6 : if (poDstFDefn)
1977 5 : nDstFieldCount = poDstFDefn->GetFieldCount();
1978 15 : for( iField=0; papszSelFields[iField] != NULL; iField++)
1979 : {
1980 9 : int iSrcField = poSrcFDefn->GetFieldIndex(papszSelFields[iField]);
1981 9 : if (iSrcField >= 0)
1982 : {
1983 9 : OGRFieldDefn* poSrcFieldDefn = poSrcFDefn->GetFieldDefn(iSrcField);
1984 9 : OGRFieldDefn oFieldDefn( poSrcFieldDefn );
1985 :
1986 9 : if (papszFieldTypesToString != NULL &&
1987 : (CSLFindString(papszFieldTypesToString, "All") != -1 ||
1988 : CSLFindString(papszFieldTypesToString,
1989 : OGRFieldDefn::GetFieldTypeName(poSrcFieldDefn->GetType())) != -1))
1990 : {
1991 0 : oFieldDefn.SetType(OFTString);
1992 : }
1993 :
1994 : /* The field may have been already created at layer creation */
1995 9 : int iDstField = -1;
1996 9 : if (poDstFDefn)
1997 8 : iDstField = poDstFDefn->GetFieldIndex(oFieldDefn.GetNameRef());
1998 9 : if (iDstField >= 0)
1999 : {
2000 0 : panMap[iSrcField] = iDstField;
2001 : }
2002 9 : else if (poDstLayer->CreateField( &oFieldDefn ) == OGRERR_NONE)
2003 : {
2004 : /* now that we've created a field, GetLayerDefn() won't return NULL */
2005 9 : if (poDstFDefn == NULL)
2006 1 : poDstFDefn = poDstLayer->GetLayerDefn();
2007 :
2008 : /* Sanity check : if it fails, the driver is buggy */
2009 9 : if (poDstFDefn != NULL &&
2010 : poDstFDefn->GetFieldCount() != nDstFieldCount + 1)
2011 : {
2012 : CPLError(CE_Warning, CPLE_AppDefined,
2013 : "The output driver has claimed to have added the %s field, but it did not!",
2014 0 : oFieldDefn.GetNameRef() );
2015 : }
2016 : else
2017 : {
2018 9 : panMap[iSrcField] = nDstFieldCount;
2019 9 : nDstFieldCount ++;
2020 : }
2021 9 : }
2022 : }
2023 : else
2024 : {
2025 : fprintf( stderr, "Field '%s' not found in source layer.\n",
2026 0 : papszSelFields[iField] );
2027 0 : if( !bSkipFailures )
2028 : {
2029 0 : VSIFree(panMap);
2030 0 : CSLDestroy(papszTransformOptions);
2031 0 : return FALSE;
2032 : }
2033 : }
2034 : }
2035 :
2036 : /* -------------------------------------------------------------------- */
2037 : /* Use SetIgnoredFields() on source layer if available */
2038 : /* -------------------------------------------------------------------- */
2039 6 : if (poSrcLayer->TestCapability(OLCIgnoreFields))
2040 : {
2041 : int iSrcField;
2042 2 : char** papszIgnoredFields = NULL;
2043 2 : int bUseIgnoredFields = TRUE;
2044 2 : char** papszWHEREUsedFields = NULL;
2045 :
2046 2 : if (pszWHERE)
2047 : {
2048 : /* We must not ignore fields used in the -where expression (#4015) */
2049 1 : OGRFeatureQuery oFeatureQuery;
2050 1 : if ( oFeatureQuery.Compile( poSrcLayer->GetLayerDefn(), pszWHERE ) == OGRERR_NONE )
2051 : {
2052 1 : papszWHEREUsedFields = oFeatureQuery.GetUsedFields();
2053 : }
2054 : else
2055 : {
2056 0 : bUseIgnoredFields = FALSE;
2057 1 : }
2058 : }
2059 :
2060 8 : for(iSrcField=0;iSrcField<poSrcFDefn->GetFieldCount();iSrcField++)
2061 : {
2062 : const char* pszFieldName =
2063 6 : poSrcFDefn->GetFieldDefn(iSrcField)->GetNameRef();
2064 6 : int bFieldRequested = FALSE;
2065 10 : for( iField=0; papszSelFields[iField] != NULL; iField++)
2066 : {
2067 6 : if (strcmp(pszFieldName, papszSelFields[iField]) == 0)
2068 : {
2069 2 : bFieldRequested = TRUE;
2070 2 : break;
2071 : }
2072 : }
2073 6 : bFieldRequested |= CSLFindString(papszWHEREUsedFields, pszFieldName) >= 0;
2074 6 : bFieldRequested |= (pszZField != NULL && strcmp(pszFieldName, pszZField) == 0);
2075 :
2076 : /* If source field not requested, add it to ignored files list */
2077 6 : if (!bFieldRequested)
2078 3 : papszIgnoredFields = CSLAddString(papszIgnoredFields, pszFieldName);
2079 : }
2080 2 : if (bUseIgnoredFields)
2081 2 : poSrcLayer->SetIgnoredFields((const char**)papszIgnoredFields);
2082 2 : CSLDestroy(papszIgnoredFields);
2083 2 : CSLDestroy(papszWHEREUsedFields);
2084 : }
2085 : }
2086 74 : else if( !bAppend )
2087 : {
2088 68 : int nDstFieldCount = 0;
2089 68 : if (poDstFDefn)
2090 66 : nDstFieldCount = poDstFDefn->GetFieldCount();
2091 502 : for( iField = 0; iField < nSrcFieldCount; iField++ )
2092 : {
2093 434 : OGRFieldDefn* poSrcFieldDefn = poSrcFDefn->GetFieldDefn(iField);
2094 434 : OGRFieldDefn oFieldDefn( poSrcFieldDefn );
2095 :
2096 434 : if (papszFieldTypesToString != NULL &&
2097 : (CSLFindString(papszFieldTypesToString, "All") != -1 ||
2098 : CSLFindString(papszFieldTypesToString,
2099 : OGRFieldDefn::GetFieldTypeName(poSrcFieldDefn->GetType())) != -1))
2100 : {
2101 0 : oFieldDefn.SetType(OFTString);
2102 : }
2103 :
2104 : /* The field may have been already created at layer creation */
2105 434 : int iDstField = -1;
2106 434 : if (poDstFDefn)
2107 432 : iDstField = poDstFDefn->GetFieldIndex(oFieldDefn.GetNameRef());
2108 434 : if (iDstField >= 0)
2109 : {
2110 285 : panMap[iField] = iDstField;
2111 : }
2112 149 : else if (poDstLayer->CreateField( &oFieldDefn ) == OGRERR_NONE)
2113 : {
2114 : /* now that we've created a field, GetLayerDefn() won't return NULL */
2115 149 : if (poDstFDefn == NULL)
2116 2 : poDstFDefn = poDstLayer->GetLayerDefn();
2117 :
2118 : /* Sanity check : if it fails, the driver is buggy */
2119 149 : if (poDstFDefn != NULL &&
2120 : poDstFDefn->GetFieldCount() != nDstFieldCount + 1)
2121 : {
2122 : CPLError(CE_Warning, CPLE_AppDefined,
2123 : "The output driver has claimed to have added the %s field, but it did not!",
2124 0 : oFieldDefn.GetNameRef() );
2125 : }
2126 : else
2127 : {
2128 149 : panMap[iField] = nDstFieldCount;
2129 149 : nDstFieldCount ++;
2130 : }
2131 : }
2132 : }
2133 : }
2134 : else
2135 : {
2136 : /* For an existing layer, build the map by fetching the index in the destination */
2137 : /* layer for each source field */
2138 6 : if (poDstFDefn == NULL)
2139 : {
2140 0 : fprintf( stderr, "poDstFDefn == NULL.\n" );
2141 0 : VSIFree(panMap);
2142 0 : CSLDestroy(papszTransformOptions);
2143 0 : return FALSE;
2144 : }
2145 :
2146 24 : for( iField = 0; iField < nSrcFieldCount; iField++ )
2147 : {
2148 18 : OGRFieldDefn* poSrcFieldDefn = poSrcFDefn->GetFieldDefn(iField);
2149 18 : int iDstField = poDstFDefn->GetFieldIndex(poSrcFieldDefn->GetNameRef());
2150 18 : if (iDstField >= 0)
2151 18 : panMap[iField] = iDstField;
2152 : }
2153 : }
2154 :
2155 : /* -------------------------------------------------------------------- */
2156 : /* Transfer features. */
2157 : /* -------------------------------------------------------------------- */
2158 : OGRFeature *poFeature;
2159 80 : int nFeaturesInTransaction = 0;
2160 80 : GIntBig nCount = 0; /* written + failed */
2161 80 : GIntBig nFeaturesWritten = 0;
2162 :
2163 80 : int iSrcZField = -1;
2164 80 : if (pszZField != NULL)
2165 : {
2166 3 : iSrcZField = poSrcFDefn->GetFieldIndex(pszZField);
2167 : }
2168 :
2169 80 : poSrcLayer->ResetReading();
2170 :
2171 80 : if( nGroupTransactions )
2172 80 : poDstLayer->StartTransaction();
2173 :
2174 125232 : while( TRUE )
2175 : {
2176 125312 : OGRFeature *poDstFeature = NULL;
2177 :
2178 125312 : if( nFIDToFetch != OGRNullFID )
2179 : {
2180 : // Only fetch feature on first pass.
2181 2 : if( nFeaturesInTransaction == 0 )
2182 1 : poFeature = poSrcLayer->GetFeature(nFIDToFetch);
2183 : else
2184 1 : poFeature = NULL;
2185 : }
2186 : else
2187 125310 : poFeature = poSrcLayer->GetNextFeature();
2188 :
2189 125312 : if( poFeature == NULL )
2190 : break;
2191 :
2192 125232 : int nParts = 0;
2193 125232 : int nIters = 1;
2194 125232 : if (bExplodeCollections)
2195 : {
2196 2 : OGRGeometry* poSrcGeometry = poFeature->GetGeometryRef();
2197 2 : if (poSrcGeometry)
2198 : {
2199 2 : switch (wkbFlatten(poSrcGeometry->getGeometryType()))
2200 : {
2201 : case wkbMultiPoint:
2202 : case wkbMultiLineString:
2203 : case wkbMultiPolygon:
2204 : case wkbGeometryCollection:
2205 1 : nParts = ((OGRGeometryCollection*)poSrcGeometry)->getNumGeometries();
2206 1 : nIters = nParts;
2207 1 : if (nIters == 0)
2208 0 : nIters = 1;
2209 : default:
2210 : break;
2211 : }
2212 : }
2213 : }
2214 :
2215 250465 : for(int iPart = 0; iPart < nIters; iPart++)
2216 : {
2217 125233 : if( ++nFeaturesInTransaction == nGroupTransactions )
2218 : {
2219 628 : poDstLayer->CommitTransaction();
2220 628 : poDstLayer->StartTransaction();
2221 628 : nFeaturesInTransaction = 0;
2222 : }
2223 :
2224 125233 : CPLErrorReset();
2225 125233 : poDstFeature = OGRFeature::CreateFeature( poDstLayer->GetLayerDefn() );
2226 :
2227 125233 : if( poDstFeature->SetFrom( poFeature, panMap, TRUE ) != OGRERR_NONE )
2228 : {
2229 0 : if( nGroupTransactions )
2230 0 : poDstLayer->CommitTransaction();
2231 :
2232 : CPLError( CE_Failure, CPLE_AppDefined,
2233 : "Unable to translate feature %ld from layer %s.\n",
2234 0 : poFeature->GetFID(), poSrcFDefn->GetName() );
2235 :
2236 0 : OGRFeature::DestroyFeature( poFeature );
2237 0 : OGRFeature::DestroyFeature( poDstFeature );
2238 0 : VSIFree(panMap);
2239 0 : CSLDestroy(papszTransformOptions);
2240 0 : return FALSE;
2241 : }
2242 :
2243 125233 : if( bPreserveFID )
2244 0 : poDstFeature->SetFID( poFeature->GetFID() );
2245 :
2246 125233 : OGRGeometry* poDstGeometry = poDstFeature->GetGeometryRef();
2247 125233 : if (poDstGeometry != NULL)
2248 : {
2249 24308 : if (nParts > 0)
2250 : {
2251 : /* For -explodecollections, extract the iPart(th) of the geometry */
2252 2 : OGRGeometry* poPart = ((OGRGeometryCollection*)poDstGeometry)->getGeometryRef(iPart);
2253 2 : ((OGRGeometryCollection*)poDstGeometry)->removeGeometry(iPart, FALSE);
2254 2 : poDstFeature->SetGeometryDirectly(poPart);
2255 2 : poDstGeometry = poPart;
2256 : }
2257 :
2258 24308 : if (iSrcZField != -1)
2259 : {
2260 30 : SetZ(poDstGeometry, poFeature->GetFieldAsDouble(iSrcZField));
2261 : /* This will correct the coordinate dimension to 3 */
2262 30 : OGRGeometry* poDupGeometry = poDstGeometry->clone();
2263 30 : poDstFeature->SetGeometryDirectly(poDupGeometry);
2264 30 : poDstGeometry = poDupGeometry;
2265 : }
2266 :
2267 24308 : if (eGeomOp == SEGMENTIZE)
2268 : {
2269 10 : if (dfGeomOpParam > 0)
2270 10 : poDstGeometry->segmentize(dfGeomOpParam);
2271 : }
2272 24298 : else if (eGeomOp == SIMPLIFY_PRESERVE_TOPOLOGY)
2273 : {
2274 0 : if (dfGeomOpParam > 0)
2275 : {
2276 0 : OGRGeometry* poNewGeom = poDstGeometry->SimplifyPreserveTopology(dfGeomOpParam);
2277 0 : if (poNewGeom)
2278 : {
2279 0 : poDstFeature->SetGeometryDirectly(poNewGeom);
2280 0 : poDstGeometry = poNewGeom;
2281 : }
2282 : }
2283 : }
2284 :
2285 24308 : if (poClipSrc)
2286 : {
2287 24 : OGRGeometry* poClipped = poDstGeometry->Intersection(poClipSrc);
2288 24 : if (poClipped == NULL || poClipped->IsEmpty())
2289 : {
2290 12 : OGRGeometryFactory::destroyGeometry(poClipped);
2291 12 : goto end_loop;
2292 : }
2293 12 : poDstFeature->SetGeometryDirectly(poClipped);
2294 12 : poDstGeometry = poClipped;
2295 : }
2296 :
2297 24310 : if( poCT != NULL || papszTransformOptions != NULL)
2298 : {
2299 : OGRGeometry* poReprojectedGeom =
2300 14 : OGRGeometryFactory::transformWithOptions(poDstGeometry, poCT, papszTransformOptions);
2301 14 : if( poReprojectedGeom == NULL )
2302 : {
2303 0 : if( nGroupTransactions )
2304 0 : poDstLayer->CommitTransaction();
2305 :
2306 : fprintf( stderr, "Failed to reproject feature %d (geometry probably out of source or destination SRS).\n",
2307 0 : (int) poFeature->GetFID() );
2308 0 : if( !bSkipFailures )
2309 : {
2310 0 : OGRFeature::DestroyFeature( poFeature );
2311 0 : OGRFeature::DestroyFeature( poDstFeature );
2312 0 : VSIFree(panMap);
2313 0 : CSLDestroy(papszTransformOptions);
2314 0 : return FALSE;
2315 : }
2316 : }
2317 :
2318 14 : poDstFeature->SetGeometryDirectly(poReprojectedGeom);
2319 14 : poDstGeometry = poReprojectedGeom;
2320 : }
2321 24282 : else if (poOutputSRS != NULL)
2322 : {
2323 24228 : poDstGeometry->assignSpatialReference(poOutputSRS);
2324 : }
2325 :
2326 24296 : if (poClipDst)
2327 : {
2328 20 : OGRGeometry* poClipped = poDstGeometry->Intersection(poClipDst);
2329 20 : if (poClipped == NULL || poClipped->IsEmpty())
2330 : {
2331 12 : OGRGeometryFactory::destroyGeometry(poClipped);
2332 12 : goto end_loop;
2333 : }
2334 :
2335 8 : poDstFeature->SetGeometryDirectly(poClipped);
2336 8 : poDstGeometry = poClipped;
2337 : }
2338 :
2339 24284 : if( bForceToPolygon )
2340 : {
2341 : poDstFeature->SetGeometryDirectly(
2342 : OGRGeometryFactory::forceToPolygon(
2343 10 : poDstFeature->StealGeometry() ) );
2344 : }
2345 24274 : else if( bForceToMultiPolygon )
2346 : {
2347 : poDstFeature->SetGeometryDirectly(
2348 : OGRGeometryFactory::forceToMultiPolygon(
2349 14 : poDstFeature->StealGeometry() ) );
2350 : }
2351 24260 : else if ( bForceToMultiLineString )
2352 : {
2353 : poDstFeature->SetGeometryDirectly(
2354 : OGRGeometryFactory::forceToMultiLineString(
2355 0 : poDstFeature->StealGeometry() ) );
2356 : }
2357 : }
2358 :
2359 125209 : CPLErrorReset();
2360 125209 : if( poDstLayer->CreateFeature( poDstFeature ) == OGRERR_NONE )
2361 : {
2362 125209 : nFeaturesWritten ++;
2363 : }
2364 0 : else if( !bSkipFailures )
2365 : {
2366 0 : if( nGroupTransactions )
2367 0 : poDstLayer->RollbackTransaction();
2368 :
2369 0 : OGRFeature::DestroyFeature( poFeature );
2370 0 : OGRFeature::DestroyFeature( poDstFeature );
2371 0 : VSIFree(panMap);
2372 0 : CSLDestroy(papszTransformOptions);
2373 0 : return FALSE;
2374 : }
2375 :
2376 : end_loop:
2377 125233 : OGRFeature::DestroyFeature( poDstFeature );
2378 : }
2379 :
2380 125232 : OGRFeature::DestroyFeature( poFeature );
2381 :
2382 : /* Report progress */
2383 125232 : nCount ++;
2384 125232 : if (pfnProgress)
2385 10 : pfnProgress(nCount * 1.0 / nCountLayerFeatures, "", pProgressArg);
2386 : }
2387 :
2388 80 : if( nGroupTransactions )
2389 80 : poDstLayer->CommitTransaction();
2390 :
2391 : CPLDebug("OGR2OGR", CPL_FRMT_GIB " features written in layer '%s'",
2392 80 : nFeaturesWritten, pszNewLayerName);
2393 :
2394 : /* -------------------------------------------------------------------- */
2395 : /* Cleaning */
2396 : /* -------------------------------------------------------------------- */
2397 80 : OGRCoordinateTransformation::DestroyCT(poCT);
2398 :
2399 80 : VSIFree(panMap);
2400 80 : CSLDestroy(papszTransformOptions);
2401 :
2402 80 : return TRUE;
2403 : }
2404 :
|