[OSGeo Africa] Batch conversion from shp to kml

Zibusiso Ncube ncubezedm at gmail.com
Wed Aug 17 00:57:35 PDT 2016


Apologies for the late delivery🙈

here is something you can use for that conversion. its two files the
main.py and ogr2ogr.py .

main.py is what you run (for the sake of ease, edit and run it using IDLE
come with your python installation but whatever ide can do the job.I chose
IDLE for the simplicitity to answer you question.

1- edit the file location see the attachment/image below  (osgeoquestion -
change file location.png)

[image: Inline image 1]
change to the location of your files

2- just make sure the ogr2ogr.py file is in the same folder as the main.py.
this is a python port of the GDAL cpp ogr2ogr.

[image: Inline image 2]

3 - if you are using IDLE ...run the main.py

[image: Inline image 3]

lastly if you dont have GDAL installed go to...

https://sandbox.idre.ucla.edu/sandbox/tutorials/installing-gdal-for-windows

read STEP 2 ....this guy explains so nicely...its a breeze

i have attached the main.py and ogr2ogr.py python port script.

Give me a shout through a personal email, if your are having issues.


Regards

Zibusiso M Ncube


On Mon, Aug 15, 2016 at 3:25 PM, Gerhard Brits <BritsJG at eskom.co.za> wrote:

> HI Mnqweno
>
>
>
> Below is a snippet from a python I use to import into Oracle spatial Using
> gdal. Rather than using ogr2ogr Python module that can be a bit difficult
> get to work. Call the required windows function from python using
> subprocess. In the snippet you will need to change the OCI part to KML.
>
>
>
> See below:
>
>
>
> result = subprocess.Popen('ogr2ogr -f OCI OCI:username/password at 111.11.
> 11.111:1521/gisqa {0} -lco DIM=2 -lco SRID=4148 -lco INDEX=NO -lco
> DIMINFO_X="-180,180,1" -lco DIMINFO_Y="-90,90,1" -lco
> GEOMETRY_NAME="GEOM"'.format(out),stdout= subprocess.PIPE, stderr=
> subprocess.PIPE, shell = True)
>
>
>
> Please check the org2ogr documentation for kml creation options.
>
>
>
> Regards
>
>
>
> -----Original Message-----
> From: Africa [mailto:africa-bounces at lists.osgeo.org] On Behalf Of
> africa-request at lists.osgeo.org
> Sent: 15 August 2016 03:12 PM
> To: africa at lists.osgeo.org
> Subject: Africa Digest, Vol 114, Issue 26
>
>
>
> Send Africa mailing list submissions to
>
>                africa at lists.osgeo.org
>
>
>
> To subscribe or unsubscribe via the World Wide Web, visit
>
>                http://lists.osgeo.org/mailman/listinfo/africa
>
> or, via email, send a message with subject or body 'help' to
>
>                africa-request at lists.osgeo.org
>
>
>
> You can reach the person managing the list at
>
>                africa-owner at lists.osgeo.org
>
>
>
> When replying, please edit your Subject line so it is more specific than
> "Re: Contents of Africa digest..."
>
>
>
>
>
> Today's Topics:
>
>
>
>    1. Re: Batch conversion from shp to kml (Zibusiso Ncube)
>
>    2. Re: Batch conversion from shp to kml (Nditsheni Matsheketsheke)
>
>
>
>
>
> ----------------------------------------------------------------------
>
>
>
> Message: 1
>
> Date: Mon, 15 Aug 2016 15:11:51 +0200
>
> From: Zibusiso Ncube <ncubezedm at gmail.com>
>
> To: Africa local chapter discussions <africa at lists.osgeo.org>
>
> Subject: Re: [OSGeo Africa] Batch conversion from shp to kml
>
> Message-ID:
>
>                <CAHiii_YX2huxUhN1a2CsGUcOjQ3WBqf9_
> obQim8y2pheRCzR+w at mail.gmail.com>
>
> Content-Type: text/plain; charset="utf-8"
>
>
>
> Hi Mnqweno
>
>
>
> i realised i had some errors in the little idea i sent earlier...maybe try
> and modify this one i wrote quickly ..it might have some errors so just
> play around with it till it works and if i have time i will write someting
> for you tomorrow.
>
>
>
> '''
>
> Created on 15 Aug 2016
>
>
>
> @author: NcubeZ
>
> '''
>
> """
>
> download and install your system specific GDAL binaries from
> https://trac.osgeo.org/gdal/wiki/DownloadingGdalBinaries
>
> or ask through another email and gurus like Tim can help you
>
>
>
> """
>
> from convertor import ogr2ogr
>
> import os
>
>
>
> from osgeo import ogr
>
>
>
>
>
> def filePathNamesList(directoryPath, extension):
>
>     """ List of all files of a specific extension within a specific
> directory
>
>
>
>         path - directory in which the files are contained e.g
> C:\\dir\\subDir\\subSubDir\\subSubSubDir
>
>         extension - file extension e.g. .txt
>
>
>
>     """
>
>     fileList=[]
>
>     for f in os.listdir(directoryPath):
>
>         if f.endswith(extension):
>
>             fileList.append(directoryPath +"\\" +f)
>
>
>
>     return fileList
>
>
>
> def convertshptokml(outputPath,inputPath):
>
>     """ OGR2OGR """
>
>     ogr2ogr.main(['-f', 'KML', outputPath,inputPath])
>
>
>
>     #################
>
>     #in your main
>
>     #################
>
>
>
>
>
> def main():
>
>
>
>     #pathList=None
>
>
>
>    '''
>
>     you could add some method to iterate through sub directories and get
> all path names
>
>     and returns a fullist of all shpfiles within your work directory
> instead of my smallanyana
>
>     methodinyana i used as an example
>
>    but for now it is just the input of directory where your shapefile are
> immediately contained, it will not search further in sub directories '''
>
>
>
>     pathList=filePathNamesList(r"C:\Users\Zibusiso\Desktop\
> TestShapefiles",
>
> extension)
>
>     extension=".shp"
>
>
>
>     #print(pathList)
>
>
>
>     for shpPath in pathList:
>
>         #remove .shp and add .kml to path name
>
>         kmlPath=path[:-4]+".kml"
>
>         convertshptokml(kmlPath, shpPath)
>
>         outputPath=None
>
>
>
>
>
> if __name__ == "__main__":
>
>     main()
>
>
>
>
>
> Regards
>
>
>
> Zibusiso M Ncube
>
>
>
>
>
> On Mon, Aug 15, 2016 at 1:04 PM, Mnqweno Mnyengeza <
> mnqwenom at statssa.gov.za>
>
> wrote:
>
>
>
> > Dear All
>
> >
>
> > I need to convert approximately thirteen million  points from shp2kml
>
> > using QGIS. I have already split the points into their respective
>
> > provinces, districts and the lowest level of demarcation which is an
>
> > enumeration area (EA) here at Statistics South Africa. The output file
>
> > of the split is the sub-folder named the EA reference number and
>
> > containing the points and polygon of that particular EA. I now need to
>
> > batch process this conversion using QGIS batch file processor if any
>
> > is available or any other free open source tool that can easily serve
> the purpose.
>
> >
>
> > Please assist
>
> >
>
> >
>
> > Kind regards
>
> >
>
> > Mnqweno Mnyengeza (Mr)
>
> >
>
> > Professional GIS Practitioner
>
> > Geography
>
> > 082 9048267 (Mobile)
>
> > Statistics South Africa
>
> > "..*.people are very quick to notice the change in your attitude
>
> > towards them but always ignore their unacceptable behavior that led to
>
> > your change* ....."
>
> >
>
> >
>
> >
>
> >
>
> > _______________________________________________
>
> > Africa mailing list
>
> > Africa at lists.osgeo.org
>
> > You can UNSUBSCRIBE at http://lists.osgeo.org/mailman/listinfo/africa
>
> >
>
> -------------- next part --------------
>
> An HTML attachment was scrubbed...
>
> URL: <http://lists.osgeo.org/pipermail/africa/attachments/
> 20160815/b521fb76/attachment-0001.html>
>
>
>
> ------------------------------
>
>
>
> Message: 2
>
> Date: Mon, 15 Aug 2016 14:33:12 +0200
>
> From: Nditsheni Matsheketsheke <ndicheni at gmail.com>
>
> To: Africa local chapter discussions <africa at lists.osgeo.org>
>
> Subject: Re: [OSGeo Africa] Batch conversion from shp to kml
>
> Message-ID:
>
>                <CACDPLN7tPYifVRtiEesULNytDyuXGzLxa8A__z3Cnp9ibTL=Ug at mail.
> gmail.com>
>
> Content-Type: text/plain; charset="utf-8"
>
>
>
> in qgis
>
>
>
> go to selection and choose how you want to select them
>
>
>
> [image: Inline image 2]
>
>
>
> after selecting all points, go to layer, right click, save as, a new
> dialog box will pop up named  save vector layer as
>
>
>
> [image: Inline image 4]
>
>
>
> change format from ESRI Shapefile to KML then still in the same dialig box
> change encoding to save only selected features
>
>
>
> [image: Inline image 5]
>
>
>
> then browse and save it in workspace
>
> ok.
>
>
>
> There you go
>
>
>
> On Mon, Aug 15, 2016 at 2:09 PM, Zoltan Szecsei <zoltans at geograph.co.za>
>
> wrote:
>
>
>
> > Hi,
>
> >
>
> > shp2kml is a product, you do realise?
>
> >
>
> > Presumably you mean you have a bunch of SHP files and want them in KML
>
> > format but don't want to use shp2kml?
>
> >
>
> >
>
> > Try ogr2ogr - using the command-line approach you should have zero
>
> > difficulties doing it "in a snap"
>
> >
>
> >
>
> > Regards,
>
> >
>
> > Zoltan
>
> >
>
> > On 2016-08-15 13:04, Mnqweno Mnyengeza wrote:
>
> >
>
> > Dear All
>
> >
>
> > I need to convert approximately thirteen million  points *from shp2kml
>
> > using QGIS*. I have already split the points into their respective
>
> > provinces, districts and the lowest level of demarcation which is an
>
> > enumeration area (EA) here at Statistics South Africa. The output file
>
> > of the split is the sub-folder named the EA reference number and
>
> > containing the points and polygon of that particular EA. I now need to
>
> > batch process this conversion using QGIS batch file processor if any
>
> > is available or any other free open source tool that can easily serve
> the purpose.
>
> >
>
> > Please assist
>
> >
>
> >
>
> > Kind regards
>
> >
>
> > Mnqweno Mnyengeza (Mr)
>
> >
>
> > Professional GIS Practitioner
>
> > Geography
>
> > 082 9048267 (Mobile)
>
> > Statistics South Africa
>
> >
>
> >
>
> >
>
> > _______________________________________________
>
> > Africa mailing list
>
> > Africa at lists.osgeo.org
>
> > You can UNSUBSCRIBE at http://lists.osgeo.org/mailman/listinfo/africa
>
> >
>
>
>
>
>
>
>
> --
>
>
>
> *Names      :Matsheketsheke Nnditsheni Jonathan*
>
>
>
>
>
> *Position    : Research Executive: Mapping AdministratorCompany  :
>
> Continental Outdoor MediaEmail        :ndicheni at gmail.com
>
> <ndicheni at gmail.com> and jonathanm at continental.com
>
> <jonathan at nrmconsulting.co.za>*
>
> * <http://www.nrmconsulting.co.za/>*
>
> *Cell           :0720324899 *
>
> *Tel            :011 514 1612 *
>
> -------------- next part --------------
>
> An HTML attachment was scrubbed...
>
> URL: <http://lists.osgeo.org/pipermail/africa/attachments/
> 20160815/520a1c5c/attachment.html>
>
> -------------- next part --------------
>
> A non-text attachment was scrubbed...
>
> Name: image.png
>
> Type: image/png
>
> Size: 67556 bytes
>
> Desc: not available
>
> URL: <http://lists.osgeo.org/pipermail/africa/attachments/
> 20160815/520a1c5c/attachment.png>
>
> -------------- next part --------------
>
> A non-text attachment was scrubbed...
>
> Name: image.png
>
> Type: image/png
>
> Size: 10989 bytes
>
> Desc: not available
>
> URL: <http://lists.osgeo.org/pipermail/africa/attachments/
> 20160815/520a1c5c/attachment-0001.png>
>
> -------------- next part --------------
>
> A non-text attachment was scrubbed...
>
> Name: image.png
>
> Type: image/png
>
> Size: 65734 bytes
>
> Desc: not available
>
> URL: <http://lists.osgeo.org/pipermail/africa/attachments/
> 20160815/520a1c5c/attachment-0002.png>
>
>
>
> ------------------------------
>
>
>
> Subject: Digest Footer
>
>
>
> _______________________________________________
>
> Africa mailing list
>
> Africa at lists.osgeo.org
>
> http://lists.osgeo.org/mailman/listinfo/africa
>
>
>
> ------------------------------
>
>
>
> End of Africa Digest, Vol 114, Issue 26
>
> ***************************************
>
> I'm part of the 49Million initiative...
> www.eskom.co.za/idm
>
> NB: This Email and its contents are subject to the Eskom Holdings SOC
> Limited EMAIL LEGAL NOTICE which can be viewed at
> http://www.eskom.co.za/Pages/Email_Legal_Spam_Disclaimer.aspx
>
> _______________________________________________
> Africa mailing list
> Africa at lists.osgeo.org
> You can UNSUBSCRIBE at http://lists.osgeo.org/mailman/listinfo/africa
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osgeo.org/pipermail/africa/attachments/20160817/799d9b2e/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: osgeoquestion - same location.png
Type: image/png
Size: 84321 bytes
Desc: not available
URL: <http://lists.osgeo.org/pipermail/africa/attachments/20160817/799d9b2e/attachment-0003.png>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: osgeoquestion-run in idle.png
Type: image/png
Size: 35774 bytes
Desc: not available
URL: <http://lists.osgeo.org/pipermail/africa/attachments/20160817/799d9b2e/attachment-0004.png>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: osgeoquestion - change file location.png
Type: image/png
Size: 31769 bytes
Desc: not available
URL: <http://lists.osgeo.org/pipermail/africa/attachments/20160817/799d9b2e/attachment-0005.png>
-------------- next part --------------
#*****************************************************************************
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
#
#**************************************************************************

import sys
import os
from os.path import basename

import ogr2ogr
import os
import sys

from osgeo import ogr
#import KmlConvertor

def filePathNamesList(directoryPath, extension):
    """ List of all files of a specific extension within a specific directory
    
        path - directory in which the files are contained e.g C:\\dir\\subDir\\subSubDir\\subSubSubDir
        extension - file extension e.g. .txt
        
    """
    fileList=[]
    
    #===========================================================================
    # for f in os.listdir(directoryPath):
    #     if f.endswith(extension):
    #         fileList.append(directoryPath +"\\" +f)
    #         
    # return fileList
    #===========================================================================

    fileList = [os.path.join(root, name)
             for root, dirs, files in os.walk(directoryPath)
             for name in files
             if name.endswith((extension))]
    
    return fileList

def convertSHPToKML(inputPath,outputPath):
    """ OGR2OGR 
    
        I Did Not write This just adapted it. Make sure the ogr2ogr.py file
        is included with these python files
    
    """    
    ogr2ogr.main(['','-f','KML',outputPath,inputPath])
    
def progression(percent, bar = 20):
    sys.stdout.write("\r")
    progress = ""
    for i in range(bar):
        if i < int(bar * percent):
            progress += "#"
        else:
            progress += " "
    sys.stdout.write("[ %s ] %.2f%%" % (progress, percent * 100))
    sys.stdout.flush()

def main():

    #pathList=None
    extension=".shp"
    
    #===========================================================================
    # Give it some time to do its work (I did not test it just wrote and assumed
    # it works ...just watch the memory and alert me if you think there are 
    # memory leaks. 
    # .... 
    #Zibusiso
    #===========================================================================
    
    pathList= filePathNamesList(r"C:\Users\NcubeZ\Desktop\TestShapefiles", extension)
    #print(pathList)
    count=0
    for path in pathList:
        
        #check if  shpToKml folder exists and create one if it does not exists
        shpToKMLfolder = os.path.dirname(path)+"\\shpToKML"
        if not os.path.exists(shpToKMLfolder):
            os.makedirs(shpToKMLfolder)
        
        #create new filepath
        outputPath=shpToKMLfolder+"\\"+ os.path.splitext(basename(path))[0]+".kml"
        convertSHPToKML(path,outputPath)
        outputPath=None
        
        count+=1
        
        percentagefilescompleted = (float(count)/len(pathList))
        
        progression(percentagefilescompleted)

   
if __name__ == "__main__":
    main()
    
-------------- next part --------------
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#*****************************************************************************
# $Id$
#
# Project:  OpenGIS Simple Features Reference Implementation
# Purpose:  Python port of a simple client for translating between formats.
# Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
#
# Port from ogr2ogr.cpp whose author is Frank Warmerdam
#
#*****************************************************************************
# Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
# Copyright (c) 1999, Frank Warmerdam
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
#**************************************************************************

# Note : this is the most direct port of ogr2ogr.cpp possible
# It could be made much more Python'ish !

import sys
import os
import stat

from osgeo import gdal
from osgeo import ogr
from osgeo import osr

###############################################################################

class ScaledProgressObject:
    def __init__(self, min, max, cbk, cbk_data = None):
        self.min = min
        self.max = max
        self.cbk = cbk
        self.cbk_data = cbk_data

###############################################################################

def ScaledProgressFunc(pct, msg, data):
    if data.cbk is None:
        return True
    return data.cbk(data.min + pct * (data.max - data.min), msg, data.cbk_data)

###############################################################################

def EQUAL(a, b):
    return a.lower() == b.lower()

###############################################################################
# Redefinition of GDALTermProgress, so that autotest/pyscripts/test_ogr2ogr_py.py
# can check that the progress bar is displayed

nLastTick = -1

def TermProgress( dfComplete, pszMessage, pProgressArg ):

    global nLastTick
    nThisTick = (int) (dfComplete * 40.0)

    if nThisTick < 0:
        nThisTick = 0
    if nThisTick > 40:
        nThisTick = 40

    # Have we started a new progress run?
    if nThisTick < nLastTick and nLastTick >= 39:
        nLastTick = -1

    if nThisTick <= nLastTick:
        return True

    while nThisTick > nLastTick:
        nLastTick = nLastTick + 1
        if (nLastTick % 4) == 0:
            sys.stdout.write('%d' % ((nLastTick / 4) * 10))
        else:
            sys.stdout.write('.')

    if nThisTick == 40:
        print(" - done." )
    else:
        sys.stdout.flush()

    return True

class TargetLayerInfo:
    def __init__(self):
        self.poDstLayer = None
        self.poCT = None
        #self.papszTransformOptions = None
        self.panMap = None
        self.iSrcZField = None

class AssociatedLayers:
    def __init__(self):
        self.poSrcLayer = None
        self.psInfo = None

#**********************************************************************
#                                main()
#**********************************************************************

bSkipFailures = False
nGroupTransactions = 200
bPreserveFID = False
nFIDToFetch = ogr.NullFID

class Enum(set):
    def __getattr__(self, name):
        if name in self:
            return name
        raise AttributeError

GeomOperation = Enum(["NONE", "SEGMENTIZE", "SIMPLIFY_PRESERVE_TOPOLOGY"])

def main(args = None, progress_func = TermProgress, progress_data = None):

    global bSkipFailures
    global nGroupTransactions
    global bPreserveFID
    global nFIDToFetch

    pszFormat = "ESRI Shapefile"
    pszDataSource = None
    pszDestDataSource = None
    papszLayers = []
    papszDSCO = []
    papszLCO = []
    bTransform = False
    bAppend = False
    bUpdate = False
    bOverwrite = False
    pszOutputSRSDef = None
    pszSourceSRSDef = None
    poOutputSRS = None
    bNullifyOutputSRS = False
    poSourceSRS = None
    pszNewLayerName = None
    pszWHERE = None
    poSpatialFilter = None
    pszSelect = None
    papszSelFields = None
    pszSQLStatement = None
    eGType = -2
    bPromoteToMulti = False
    eGeomOp = GeomOperation.NONE
    dfGeomOpParam = 0
    papszFieldTypesToString = []
    bDisplayProgress = False
    pfnProgress = None
    pProgressArg = None
    bClipSrc = False
    bWrapDateline = False
    poClipSrc = None
    pszClipSrcDS = None
    pszClipSrcSQL = None
    pszClipSrcLayer = None
    pszClipSrcWhere = None
    poClipDst = None
    pszClipDstDS = None
    pszClipDstSQL = None
    pszClipDstLayer = None
    pszClipDstWhere = None
    #pszSrcEncoding = None
    #pszDstEncoding = None
    bWrapDateline = False
    bExplodeCollections = False
    pszZField = None
    nCoordDim = -1

    if args is None:
        args = sys.argv

    args = ogr.GeneralCmdLineProcessor( args )

# --------------------------------------------------------------------
#      Processing command line arguments.
# --------------------------------------------------------------------
    if args is None:
        return False

    nArgc = len(args)

    iArg = 1
    while iArg < nArgc:
        if EQUAL(args[iArg],"-f") and iArg < nArgc-1:
            iArg = iArg + 1
            pszFormat = args[iArg]

        elif EQUAL(args[iArg],"-dsco") and iArg < nArgc-1:
            iArg = iArg + 1
            papszDSCO.append(args[iArg] )

        elif EQUAL(args[iArg],"-lco") and iArg < nArgc-1:
            iArg = iArg + 1
            papszLCO.append(args[iArg] )

        elif EQUAL(args[iArg],"-preserve_fid"):
            bPreserveFID = True

        elif len(args[iArg]) >= 5 and EQUAL(args[iArg][0:5], "-skip"):
            bSkipFailures = True
            nGroupTransactions = 1 # #2409

        elif EQUAL(args[iArg],"-append"):
            bAppend = True
            bUpdate = True

        elif EQUAL(args[iArg],"-overwrite"):
            bOverwrite = True
            bUpdate = True

        elif EQUAL(args[iArg],"-update"):
            bUpdate = True

        elif EQUAL(args[iArg],"-fid") and iArg < nArgc-1:
            iArg = iArg + 1
            nFIDToFetch = int(args[iArg])

        elif EQUAL(args[iArg],"-sql") and iArg < nArgc-1:
            iArg = iArg + 1
            pszSQLStatement = args[iArg]

        elif EQUAL(args[iArg],"-nln") and iArg < nArgc-1:
            iArg = iArg + 1
            pszNewLayerName = args[iArg]

        elif EQUAL(args[iArg],"-nlt") and iArg < nArgc-1:

            if EQUAL(args[iArg+1],"NONE"):
                eGType = ogr.wkbNone
            elif EQUAL(args[iArg+1],"GEOMETRY"):
                eGType = ogr.wkbUnknown
            elif EQUAL(args[iArg+1],"PROMOTE_TO_MULTI"):
                bPromoteToMulti = True
            elif EQUAL(args[iArg+1],"POINT"):
                eGType = ogr.wkbPoint
            elif EQUAL(args[iArg+1],"LINESTRING"):
                eGType = ogr.wkbLineString
            elif EQUAL(args[iArg+1],"POLYGON"):
                eGType = ogr.wkbPolygon
            elif EQUAL(args[iArg+1],"GEOMETRYCOLLECTION"):
                eGType = ogr.wkbGeometryCollection
            elif EQUAL(args[iArg+1],"MULTIPOINT"):
                eGType = ogr.wkbMultiPoint
            elif EQUAL(args[iArg+1],"MULTILINESTRING"):
                eGType = ogr.wkbMultiLineString
            elif EQUAL(args[iArg+1],"MULTIPOLYGON"):
                eGType = ogr.wkbMultiPolygon
            elif EQUAL(args[iArg+1],"GEOMETRY25D"):
                eGType = ogr.wkbUnknown | ogr.wkb25DBit
            elif EQUAL(args[iArg+1],"POINT25D"):
                eGType = ogr.wkbPoint25D
            elif EQUAL(args[iArg+1],"LINESTRING25D"):
                eGType = ogr.wkbLineString25D
            elif EQUAL(args[iArg+1],"POLYGON25D"):
                eGType = ogr.wkbPolygon25D
            elif EQUAL(args[iArg+1],"GEOMETRYCOLLECTION25D"):
                eGType = ogr.wkbGeometryCollection25D
            elif EQUAL(args[iArg+1],"MULTIPOINT25D"):
                eGType = ogr.wkbMultiPoint25D
            elif EQUAL(args[iArg+1],"MULTILINESTRING25D"):
                eGType = ogr.wkbMultiLineString25D
            elif EQUAL(args[iArg+1],"MULTIPOLYGON25D"):
                eGType = ogr.wkbMultiPolygon25D
            else:
                print("-nlt %s: type not recognised." % args[iArg+1])
                return False

            iArg = iArg + 1

        elif EQUAL(args[iArg],"-dim") and iArg < nArgc-1:

            nCoordDim = int(args[iArg+1])
            if nCoordDim != 2 and nCoordDim != 3:
                print("-dim %s: value not handled." % args[iArg+1])
                return False
            iArg = iArg + 1

        elif (EQUAL(args[iArg],"-tg") or \
                EQUAL(args[iArg],"-gt")) and iArg < nArgc-1:
            iArg = iArg + 1
            nGroupTransactions = int(args[iArg])

        elif EQUAL(args[iArg],"-s_srs") and iArg < nArgc-1:
            iArg = iArg + 1
            pszSourceSRSDef = args[iArg]

        elif EQUAL(args[iArg],"-a_srs") and iArg < nArgc-1:
            iArg = iArg + 1
            pszOutputSRSDef = args[iArg]
            if EQUAL(pszOutputSRSDef, "NULL") or \
               EQUAL(pszOutputSRSDef, "NONE"):
                pszOutputSRSDef = None
                bNullifyOutputSRS = True

        elif EQUAL(args[iArg],"-t_srs") and iArg < nArgc-1:
            iArg = iArg + 1
            pszOutputSRSDef = args[iArg]
            bTransform = True

        elif EQUAL(args[iArg],"-spat") and iArg + 4 < nArgc:
            oRing = ogr.Geometry(ogr.wkbLinearRing)

            oRing.AddPoint_2D( float(args[iArg+1]), float(args[iArg+2]) )
            oRing.AddPoint_2D( float(args[iArg+1]), float(args[iArg+4]) )
            oRing.AddPoint_2D( float(args[iArg+3]), float(args[iArg+4]) )
            oRing.AddPoint_2D( float(args[iArg+3]), float(args[iArg+2]) )
            oRing.AddPoint_2D( float(args[iArg+1]), float(args[iArg+2]) )

            poSpatialFilter = ogr.Geometry(ogr.wkbPolygon)
            poSpatialFilter.AddGeometry(oRing)
            iArg = iArg + 4

        elif EQUAL(args[iArg],"-where") and iArg < nArgc-1:
            iArg = iArg + 1
            pszWHERE = args[iArg]

        elif EQUAL(args[iArg],"-select") and iArg < nArgc-1:
            iArg = iArg + 1
            pszSelect = args[iArg]
            if pszSelect.find(',') != -1:
                papszSelFields = pszSelect.split(',')
            else:
                papszSelFields = pszSelect.split(' ')
            if papszSelFields[0] == '':
                papszSelFields = []

        elif EQUAL(args[iArg],"-simplify") and iArg < nArgc-1:
            iArg = iArg + 1
            eGeomOp = GeomOperation.SIMPLIFY_PRESERVE_TOPOLOGY
            dfGeomOpParam = float(args[iArg])

        elif EQUAL(args[iArg],"-segmentize") and iArg < nArgc-1:
            iArg = iArg + 1
            eGeomOp = GeomOperation.SEGMENTIZE
            dfGeomOpParam = float(args[iArg])

        elif EQUAL(args[iArg],"-fieldTypeToString") and iArg < nArgc-1:
            iArg = iArg + 1
            pszFieldTypeToString = args[iArg]
            if pszFieldTypeToString.find(',') != -1:
                tokens = pszFieldTypeToString.split(',')
            else:
                tokens = pszFieldTypeToString.split(' ')

            for token in tokens:
                if EQUAL(token,"Integer") or \
                    EQUAL(token,"Real") or \
                    EQUAL(token,"String") or \
                    EQUAL(token,"Date") or \
                    EQUAL(token,"Time") or \
                    EQUAL(token,"DateTime") or \
                    EQUAL(token,"Binary") or \
                    EQUAL(token,"IntegerList") or \
                    EQUAL(token,"RealList") or \
                    EQUAL(token,"StringList"):

                    papszFieldTypesToString.append(token)

                elif EQUAL(token,"All"):
                    papszFieldTypesToString = [ 'All' ]
                    break

                else:
                    print("Unhandled type for fieldtypeasstring option : %s " % token)
                    return Usage()

        elif EQUAL(args[iArg],"-progress"):
            bDisplayProgress = True

        #elif EQUAL(args[iArg],"-wrapdateline") )
        #{
        #    bWrapDateline = True;
        #}
        #
        elif EQUAL(args[iArg],"-clipsrc") and iArg < nArgc-1:

            bClipSrc = True
            if IsNumber(args[iArg+1]) and iArg < nArgc - 4:
                oRing = ogr.Geometry(ogr.wkbLinearRing)

                oRing.AddPoint_2D( float(args[iArg+1]), float(args[iArg+2]) )
                oRing.AddPoint_2D( float(args[iArg+1]), float(args[iArg+4]) )
                oRing.AddPoint_2D( float(args[iArg+3]), float(args[iArg+4]) )
                oRing.AddPoint_2D( float(args[iArg+3]), float(args[iArg+2]) )
                oRing.AddPoint_2D( float(args[iArg+1]), float(args[iArg+2]) )

                poClipSrc = ogr.Geometry(ogr.wkbPolygon)
                poClipSrc.AddGeometry(oRing)
                iArg = iArg + 4

            elif (len(args[iArg+1]) >= 7 and EQUAL(args[iArg+1][0:7],"POLYGON") ) or \
                  (len(args[iArg+1]) >= 12 and EQUAL(args[iArg+1][0:12],"MULTIPOLYGON") ) :
                poClipSrc = ogr.CreateGeometryFromWkt(args[iArg+1])
                if poClipSrc is None:
                    print("FAILURE: Invalid geometry. Must be a valid POLYGON or MULTIPOLYGON WKT\n")
                    return Usage()

                iArg = iArg + 1

            elif EQUAL(args[iArg+1],"spat_extent"):
                iArg = iArg + 1

            else:
                pszClipSrcDS = args[iArg+1]
                iArg = iArg + 1

        elif EQUAL(args[iArg],"-clipsrcsql") and iArg < nArgc-1:
            pszClipSrcSQL = args[iArg+1]
            iArg = iArg + 1

        elif EQUAL(args[iArg],"-clipsrclayer") and iArg < nArgc-1:
            pszClipSrcLayer = args[iArg+1]
            iArg = iArg + 1

        elif EQUAL(args[iArg],"-clipsrcwhere") and iArg < nArgc-1:
            pszClipSrcWhere = args[iArg+1]
            iArg = iArg + 1

        elif EQUAL(args[iArg],"-clipdst") and iArg < nArgc-1:

            if IsNumber(args[iArg+1]) and iArg < nArgc - 4:
                oRing = ogr.Geometry(ogr.wkbLinearRing)

                oRing.AddPoint_2D( float(args[iArg+1]), float(args[iArg+2]) )
                oRing.AddPoint_2D( float(args[iArg+1]), float(args[iArg+4]) )
                oRing.AddPoint_2D( float(args[iArg+3]), float(args[iArg+4]) )
                oRing.AddPoint_2D( float(args[iArg+3]), float(args[iArg+2]) )
                oRing.AddPoint_2D( float(args[iArg+1]), float(args[iArg+2]) )

                poClipDst = ogr.Geometry(ogr.wkbPolygon)
                poClipDst.AddGeometry(oRing)
                iArg = iArg + 4

            elif (len(args[iArg+1]) >= 7 and EQUAL(args[iArg+1][0:7],"POLYGON") ) or \
                  (len(args[iArg+1]) >= 12 and EQUAL(args[iArg+1][0:12],"MULTIPOLYGON") ) :
                poClipDst = ogr.CreateGeometryFromWkt(args[iArg+1])
                if poClipDst is None:
                    print("FAILURE: Invalid geometry. Must be a valid POLYGON or MULTIPOLYGON WKT\n")
                    return Usage()

                iArg = iArg + 1

            elif EQUAL(args[iArg+1],"spat_extent"):
                iArg = iArg + 1

            else:
                pszClipDstDS = args[iArg+1]
                iArg = iArg + 1

        elif EQUAL(args[iArg],"-clipdstsql") and iArg < nArgc-1:
            pszClipDstSQL = args[iArg+1]
            iArg = iArg + 1

        elif EQUAL(args[iArg],"-clipdstlayer") and iArg < nArgc-1:
            pszClipDstLayer = args[iArg+1]
            iArg = iArg + 1

        elif EQUAL(args[iArg],"-clipdstwhere") and iArg < nArgc-1:
            pszClipDstWhere = args[iArg+1]
            iArg = iArg + 1

        elif EQUAL(args[iArg],"-explodecollections"):
            bExplodeCollections = True

        elif EQUAL(args[iArg],"-zfield") and iArg < nArgc-1:
            pszZField = args[iArg+1]
            iArg = iArg + 1

        elif args[iArg][0] == '-':
            return Usage()

        elif pszDestDataSource is None:
            pszDestDataSource = args[iArg]
        elif pszDataSource is None:
            pszDataSource = args[iArg]
        else:
            papszLayers.append (args[iArg] )

        iArg = iArg + 1

    if pszDataSource is None:
        return Usage()

    if bPreserveFID and bExplodeCollections:
        print("FAILURE: cannot use -preserve_fid and -explodecollections at the same time\n\n")
        return Usage()

    if bClipSrc and pszClipSrcDS is not None:
        poClipSrc = LoadGeometry(pszClipSrcDS, pszClipSrcSQL, pszClipSrcLayer, pszClipSrcWhere)
        if poClipSrc is None:
            print("FAILURE: cannot load source clip geometry\n" )
            return Usage()

    elif bClipSrc and poClipSrc is None:
        if poSpatialFilter is not None:
            poClipSrc = poSpatialFilter.Clone()
        if poClipSrc is None:
            print("FAILURE: -clipsrc must be used with -spat option or a\n" + \
                  "bounding box, WKT string or datasource must be specified\n")
            return Usage()

    if pszClipDstDS is not None:
        poClipDst = LoadGeometry(pszClipDstDS, pszClipDstSQL, pszClipDstLayer, pszClipDstWhere)
        if poClipDst is None:
            print("FAILURE: cannot load dest clip geometry\n" )
            return Usage()

# --------------------------------------------------------------------
#      Open data source.
# --------------------------------------------------------------------
    poDS = ogr.Open( pszDataSource, False )

# --------------------------------------------------------------------
#      Report failure
# --------------------------------------------------------------------
    if poDS is None:
        print("FAILURE:\n" + \
                "Unable to open datasource `%s' with the following drivers." % pszDataSource)

        for iDriver in range(ogr.GetDriverCount()):
            print("  ->  " + ogr.GetDriver(iDriver).GetName() )

        return False

# --------------------------------------------------------------------
#      Try opening the output datasource as an existing, writable
# --------------------------------------------------------------------
    poODS = None
    poDriver = None

    if bUpdate:
        poODS = ogr.Open( pszDestDataSource, True )
        if poODS is None:

            if bOverwrite or bAppend:
                poODS = ogr.Open( pszDestDataSource, False )
                if poODS is None:
                    # the datasource doesn't exist at all
                    bUpdate = False
                else:
                    poODS.delete()
                    poODS = None

            if bUpdate:
                print("FAILURE:\n" +
                        "Unable to open existing output datasource `%s'." % pszDestDataSource)
                return False

        elif len(papszDSCO) > 0:
            print("WARNING: Datasource creation options ignored since an existing datasource\n" + \
                    "         being updated." )

        if poODS is not None:
            poDriver = poODS.GetDriver()

# --------------------------------------------------------------------
#      Find the output driver.
# --------------------------------------------------------------------
    if not bUpdate:
        poDriver = ogr.GetDriverByName(pszFormat)
        if poDriver is None:
            print("Unable to find driver `%s'." % pszFormat)
            print( "The following drivers are available:" )

            for iDriver in range(ogr.GetDriverCount()):
                print("  ->  %s" % ogr.GetDriver(iDriver).GetName() )

            return False

        if poDriver.TestCapability( ogr.ODrCCreateDataSource ) == False:
            print( "%s driver does not support data source creation." % pszFormat)
            return False

# --------------------------------------------------------------------
#      Special case to improve user experience when translating
#      a datasource with multiple layers into a shapefile. If the
#      user gives a target datasource with .shp and it does not exist,
#      the shapefile driver will try to create a file, but this is not
#      appropriate because here we have several layers, so create
#      a directory instead.
# --------------------------------------------------------------------
        if EQUAL(poDriver.GetName(), "ESRI Shapefile") and \
           pszSQLStatement is None and \
           (len(papszLayers) > 1 or \
            (len(papszLayers) == 0 and poDS.GetLayerCount() > 1)) and \
            pszNewLayerName is None and \
            EQUAL(os.path.splitext(pszDestDataSource)[1], ".SHP") :

            try:
                os.stat(pszDestDataSource)
            except:
                try:
                    # decimal 493 = octal 0755. Python 3 needs 0o755, but
                    # this syntax is only supported by Python >= 2.6
                    os.mkdir(pszDestDataSource, 493)
                except:
                    print("Failed to create directory %s\n"
                          "for shapefile datastore.\n" % pszDestDataSource )
                    return False

# --------------------------------------------------------------------
#      Create the output data source.
# --------------------------------------------------------------------
        poODS = poDriver.CreateDataSource( pszDestDataSource, options = papszDSCO )
        if poODS is None:
            print( "%s driver failed to create %s" % (pszFormat, pszDestDataSource ))
            return False

# --------------------------------------------------------------------
#      Parse the output SRS definition if possible.
# --------------------------------------------------------------------
    if pszOutputSRSDef is not None:
        poOutputSRS = osr.SpatialReference()
        if poOutputSRS.SetFromUserInput( pszOutputSRSDef ) != 0:
            print( "Failed to process SRS definition: %s" % pszOutputSRSDef )
            return False

# --------------------------------------------------------------------
#      Parse the source SRS definition if possible.
# --------------------------------------------------------------------
    if pszSourceSRSDef is not None:
        poSourceSRS = osr.SpatialReference()
        if poSourceSRS.SetFromUserInput( pszSourceSRSDef ) != 0:
            print( "Failed to process SRS definition: %s" % pszSourceSRSDef )
            return False

# --------------------------------------------------------------------
#      For OSM file.
# --------------------------------------------------------------------
    bSrcIsOSM = poDS.GetDriver() is not None and \
                             poDS.GetDriver().GetName() == "OSM"
    nSrcFileSize = 0
    if bSrcIsOSM and poDS.GetName() != "/vsistdin/":
        sStat = gdal.VSIStatL(poDS.GetName())
        if sStat is not None:
            nSrcFileSize = sStat.size

# --------------------------------------------------------------------
#      Special case for -sql clause.  No source layers required.
# --------------------------------------------------------------------
    if pszSQLStatement is not None:
        if pszWHERE is not None:
            print( "-where clause ignored in combination with -sql." )
        if len(papszLayers) > 0:
            print( "layer names ignored in combination with -sql." )

        poResultSet = poDS.ExecuteSQL( pszSQLStatement, poSpatialFilter, \
                                        None )

        if poResultSet is not None:
            nCountLayerFeatures = 0
            if bDisplayProgress:
                if bSrcIsOSM:
                    pfnProgress = progress_func
                    pProgressArg = progress_data

                elif not poResultSet.TestCapability(ogr.OLCFastFeatureCount):
                    print( "Progress turned off as fast feature count is not available.")
                    bDisplayProgress = False

                else:
                    nCountLayerFeatures = poResultSet.GetFeatureCount()
                    pfnProgress = progress_func
                    pProgressArg = progress_data

# --------------------------------------------------------------------
#      Special case to improve user experience when translating into
#      single file shapefile and source has only one layer, and that
#      the layer name isn't specified
# --------------------------------------------------------------------
            if EQUAL(poDriver.GetName(), "ESRI Shapefile") and \
                pszNewLayerName is None:
                try:
                    mode = os.stat(pszDestDataSource).st_mode
                    if (mode & stat.S_IFDIR) == 0:
                        pszNewLayerName = os.path.splitext(os.path.basename(pszDestDataSource))[0]
                except:
                    pass


            psInfo = SetupTargetLayer(  poDS, \
                                        poResultSet,
                                        poODS, \
                                        papszLCO, \
                                        pszNewLayerName, \
                                        bTransform, \
                                        poOutputSRS, \
                                        bNullifyOutputSRS, \
                                        poSourceSRS, \
                                        papszSelFields, \
                                        bAppend, eGType, bPromoteToMulti, nCoordDim, bOverwrite, \
                                        papszFieldTypesToString, \
                                        bWrapDateline, \
                                        bExplodeCollections, \
                                        pszZField, \
                                        pszWHERE )

            poResultSet.ResetReading()

            if psInfo is None or not TranslateLayer( psInfo, poDS, poResultSet, poODS, \
                                poOutputSRS, bNullifyOutputSRS, \
                                eGType, bPromoteToMulti, nCoordDim, \
                                eGeomOp, dfGeomOpParam, \
                                nCountLayerFeatures, \
                                poClipSrc, poClipDst, \
                                bExplodeCollections, \
                                nSrcFileSize, None, \
                                pfnProgress, pProgressArg ):
                print(
                        "Terminating translation prematurely after failed\n" + \
                        "translation from sql statement." )

                return False

            poDS.ReleaseResultSet( poResultSet )


# --------------------------------------------------------------------
#      Special case for layer interleaving mode.
# --------------------------------------------------------------------
    elif bSrcIsOSM and gdal.GetConfigOption("OGR_INTERLEAVED_READING", None) is None:

        gdal.SetConfigOption("OGR_INTERLEAVED_READING", "YES")

        #if (bSplitListFields)
        #{
        #    fprintf( stderr, "FAILURE: -splitlistfields not supported in this mode\n" );
        #    exit( 1 );
        #}

        nSrcLayerCount = poDS.GetLayerCount()
        pasAssocLayers = [ AssociatedLayers() for i in range(nSrcLayerCount) ]

# --------------------------------------------------------------------
#      Special case to improve user experience when translating into
#      single file shapefile and source has only one layer, and that
#      the layer name isn't specified
# --------------------------------------------------------------------

        if EQUAL(poDriver.GetName(), "ESRI Shapefile") and \
           (len(papszLayers) == 1 or nSrcLayerCount == 1) and pszNewLayerName is None:
            try:
                mode = os.stat(pszDestDataSource).st_mode
                if (mode & stat.S_IFDIR) == 0:
                    pszNewLayerName = os.path.splitext(os.path.basename(pszDestDataSource))[0]
            except:
                pass

        if bDisplayProgress and bSrcIsOSM:
            pfnProgress = progress_func
            pProgressArg = progress_data

# --------------------------------------------------------------------
#      If no target layer specified, use all source layers.
# --------------------------------------------------------------------
        if len(papszLayers) == 0:
            papszLayers = [ None for i in range(nSrcLayerCount) ]
            for iLayer in range(nSrcLayerCount):
                poLayer = poDS.GetLayer(iLayer)
                if poLayer is None:
                    print("FAILURE: Couldn't fetch advertised layer %d!" % iLayer)
                    return False

                papszLayers[iLayer] = poLayer.GetName()
        else:
            if bSrcIsOSM:
                osInterestLayers = "SET interest_layers ="
                for iLayer in range(len(papszLayers)):
                    if iLayer != 0:
                        osInterestLayers = osInterestLayers + ","
                    osInterestLayers = osInterestLayers + papszLayers[iLayer]

                poDS.ExecuteSQL(osInterestLayers, None, None)

# --------------------------------------------------------------------
#      First pass to set filters and create target layers.
# --------------------------------------------------------------------
        for iLayer in range(nSrcLayerCount):
            poLayer = poDS.GetLayer(iLayer)
            if poLayer is None:
                print("FAILURE: Couldn't fetch advertised layer %d!" % iLayer)
                return False

            pasAssocLayers[iLayer].poSrcLayer = poLayer

            if CSLFindString(papszLayers, poLayer.GetName()) >= 0:
                if pszWHERE is not None:
                    if poLayer.SetAttributeFilter( pszWHERE ) != 0:
                        print("FAILURE: SetAttributeFilter(%s) on layer '%s' failed.\n" % (pszWHERE, poLayer.GetName()) )
                        if not bSkipFailures:
                            return False

                if poSpatialFilter is not None:
                    poLayer.SetSpatialFilter( poSpatialFilter )

                psInfo = SetupTargetLayer( poDS, \
                                           poLayer, \
                                           poODS, \
                                           papszLCO, \
                                           pszNewLayerName, \
                                           bTransform, \
                                           poOutputSRS, \
                                           bNullifyOutputSRS, \
                                           poSourceSRS, \
                                           papszSelFields, \
                                           bAppend, eGType, bPromoteToMulti, nCoordDim, bOverwrite, \
                                           papszFieldTypesToString, \
                                           bWrapDateline, \
                                           bExplodeCollections, \
                                           pszZField, \
                                           pszWHERE )

                if psInfo is None and not bSkipFailures:
                    return False

                pasAssocLayers[iLayer].psInfo = psInfo
            else:
                pasAssocLayers[iLayer].psInfo = None

# --------------------------------------------------------------------
#      Second pass to process features in a interleaved layer mode.
# --------------------------------------------------------------------
        bHasLayersNonEmpty = True
        while bHasLayersNonEmpty:
            bHasLayersNonEmpty = False

            for iLayer in range(nSrcLayerCount):
                poLayer = pasAssocLayers[iLayer].poSrcLayer
                psInfo = pasAssocLayers[iLayer].psInfo
                anReadFeatureCount = [0]

                if psInfo is not None:
                    if not TranslateLayer(psInfo, poDS, poLayer, poODS, \
                                        poOutputSRS, bNullifyOutputSRS,  \
                                        eGType, bPromoteToMulti, nCoordDim, \
                                        eGeomOp, dfGeomOpParam,  \
                                        0,  \
                                        poClipSrc, poClipDst,  \
                                        bExplodeCollections,  \
                                        nSrcFileSize,  \
                                        anReadFeatureCount, \
                                        pfnProgress, pProgressArg ) \
                        and not bSkipFailures:
                        print(
                                "Terminating translation prematurely after failed\n" + \
                                "translation of layer " + poLayer.GetName() + " (use -skipfailures to skip errors)")

                        return False
                else:
                    # No matching target layer : just consumes the features

                    poFeature = poLayer.GetNextFeature()
                    while poFeature is not None:
                        anReadFeatureCount[0] = anReadFeatureCount[0] + 1
                        poFeature = poLayer.GetNextFeature()

                if anReadFeatureCount[0] != 0:
                    bHasLayersNonEmpty = True

    else:

        nLayerCount = 0
        papoLayers = []

# --------------------------------------------------------------------
#      Process each data source layer.
# --------------------------------------------------------------------
        if len(papszLayers) == 0:
            nLayerCount = poDS.GetLayerCount()
            papoLayers = [None for i in range(nLayerCount)]
            iLayer = 0

            for iLayer in range(nLayerCount):
                poLayer = poDS.GetLayer(iLayer)

                if poLayer is None:
                    print("FAILURE1: Couldn't fetch advertised layer %d!" % iLayer)
                    return False

                papoLayers[iLayer] = poLayer
                iLayer = iLayer + 1

# --------------------------------------------------------------------
#      Process specified data source layers.
# --------------------------------------------------------------------
        else:
            nLayerCount = len(papszLayers)
            papoLayers = [None for i in range(nLayerCount)]
            iLayer = 0

            for layername in papszLayers:
                poLayer = poDS.GetLayerByName(layername)

                if poLayer is None:
                    print("FAILURE: Couldn't fetch advertised layer %s!" % layername)
                    return False

                papoLayers[iLayer] = poLayer
                iLayer = iLayer + 1

        panLayerCountFeatures = [0 for i in range(nLayerCount)]
        nCountLayersFeatures = 0
        nAccCountFeatures = 0

        # First pass to apply filters and count all features if necessary
        for iLayer in range(nLayerCount):
            poLayer = papoLayers[iLayer]

            if pszWHERE is not None:
                if poLayer.SetAttributeFilter( pszWHERE ) != 0:
                    print("FAILURE: SetAttributeFilter(%s) failed." % pszWHERE)
                    if not bSkipFailures:
                        return False

            if poSpatialFilter is not None:
                poLayer.SetSpatialFilter( poSpatialFilter )

            if bDisplayProgress and not bSrcIsOSM:
                if not poLayer.TestCapability(ogr.OLCFastFeatureCount):
                    print("Progress turned off as fast feature count is not available.")
                    bDisplayProgress = False
                else:
                    panLayerCountFeatures[iLayer] = poLayer.GetFeatureCount()
                    nCountLayersFeatures += panLayerCountFeatures[iLayer]

        # Second pass to do the real job
        for iLayer in range(nLayerCount):
            poLayer = papoLayers[iLayer]

            if bDisplayProgress:
                if bSrcIsOSM:
                    pfnProgress = progress_func
                    pProgressArg = progress_data
                else:
                    pfnProgress = ScaledProgressFunc
                    pProgressArg = ScaledProgressObject( \
                            nAccCountFeatures * 1.0 / nCountLayersFeatures, \
                            (nAccCountFeatures + panLayerCountFeatures[iLayer]) * 1.0 / nCountLayersFeatures, \
                            progress_func, progress_data)

            nAccCountFeatures += panLayerCountFeatures[iLayer]

# --------------------------------------------------------------------
#      Special case to improve user experience when translating into
#      single file shapefile and source has only one layer, and that
#      the layer name isn't specified
# --------------------------------------------------------------------
            if EQUAL(poDriver.GetName(), "ESRI Shapefile") and \
                nLayerCount == 1 and pszNewLayerName is None:
                try:
                    mode = os.stat(pszDestDataSource).st_mode
                    if (mode & stat.S_IFDIR) == 0:
                        pszNewLayerName = os.path.splitext(os.path.basename(pszDestDataSource))[0]
                except:
                    pass


            psInfo = SetupTargetLayer( poDS, \
                                       poLayer, \
                                       poODS, \
                                       papszLCO, \
                                       pszNewLayerName, \
                                       bTransform, \
                                       poOutputSRS, \
                                       bNullifyOutputSRS, \
                                       poSourceSRS, \
                                       papszSelFields, \
                                       bAppend, eGType, bPromoteToMulti, nCoordDim, bOverwrite, \
                                       papszFieldTypesToString, \
                                       bWrapDateline, \
                                       bExplodeCollections, \
                                       pszZField, \
                                       pszWHERE )

            poLayer.ResetReading()

            if (psInfo is None or \
                not TranslateLayer( psInfo, poDS, poLayer, poODS, \
                                    poOutputSRS, bNullifyOutputSRS, \
                                    eGType, bPromoteToMulti, nCoordDim, \
                                    eGeomOp, dfGeomOpParam, \
                                    panLayerCountFeatures[iLayer], \
                                    poClipSrc, poClipDst, \
                                    bExplodeCollections, \
                                    nSrcFileSize, None, \
                                    pfnProgress, pProgressArg )) \
                and not bSkipFailures:
                print(
                        "Terminating translation prematurely after failed\n" + \
                        "translation of layer " + poLayer.GetLayerDefn().GetName() + " (use -skipfailures to skip errors)")

                return False

# --------------------------------------------------------------------
#      Close down.
# --------------------------------------------------------------------
    # We must explicitly destroy the output dataset in order the file
    # to be properly closed !
    poODS.Destroy()
    poDS.Destroy()

    return True

#**********************************************************************
#                               Usage()
#**********************************************************************

def Usage():

    print( "Usage: ogr2ogr [--help-general] [-skipfailures] [-append] [-update] [-gt n]\n" + \
            "               [-select field_list] [-where restricted_where] \n" + \
            "               [-progress] [-sql <sql statement>] \n" + \
            "               [-spat xmin ymin xmax ymax] [-preserve_fid] [-fid FID]\n" + \
            "               [-a_srs srs_def] [-t_srs srs_def] [-s_srs srs_def]\n" + \
            "               [-f format_name] [-overwrite] [[-dsco NAME=VALUE] ...]\n" + \
            "               [-simplify tolerance]\n" + \
            #// "               [-segmentize max_dist] [-fieldTypeToString All|(type1[,type2]*)]\n" + \
            "               [-fieldTypeToString All|(type1[,type2]*)] [-explodecollections] \n" + \
            "               dst_datasource_name src_datasource_name\n" + \
            "               [-lco NAME=VALUE] [-nln name] [-nlt type] [-dim 2|3] [layer [layer ...]]\n" + \
            "\n" + \
            " -f format_name: output file format name, possible values are:")

    for iDriver in range(ogr.GetDriverCount()):
        poDriver = ogr.GetDriver(iDriver)

        if poDriver.TestCapability( ogr.ODrCCreateDataSource ):
            print( "     -f \"" + poDriver.GetName() + "\"" )

    print( " -append: Append to existing layer instead of creating new if it exists\n" + \
            " -overwrite: delete the output layer and recreate it empty\n" + \
            " -update: Open existing output datasource in update mode\n" + \
            " -progress: Display progress on terminal. Only works if input layers have the \"fast feature count\" capability\n" + \
            " -select field_list: Comma-delimited list of fields from input layer to\n" + \
            "                     copy to the new layer (defaults to all)\n" + \
            " -where restricted_where: Attribute query (like SQL WHERE)\n" + \
            " -sql statement: Execute given SQL statement and save result.\n" + \
            " -skipfailures: skip features or layers that fail to convert\n" + \
            " -gt n: group n features per transaction (default 200)\n" + \
            " -spat xmin ymin xmax ymax: spatial query extents\n" + \
            " -simplify tolerance: distance tolerance for simplification.\n" + \
            #//" -segmentize max_dist: maximum distance between 2 nodes.\n" + \
            #//"                       Used to create intermediate points\n" + \
            " -dsco NAME=VALUE: Dataset creation option (format specific)\n" + \
            " -lco  NAME=VALUE: Layer creation option (format specific)\n" + \
            " -nln name: Assign an alternate name to the new layer\n" + \
            " -nlt type: Force a geometry type for new layer.  One of NONE, GEOMETRY,\n" + \
            "      POINT, LINESTRING, POLYGON, GEOMETRYCOLLECTION, MULTIPOINT,\n" + \
            "      MULTIPOLYGON, or MULTILINESTRING.  Add \"25D\" for 3D layers.\n" + \
            "      Default is type of source layer.\n" + \
            " -dim dimension: Force the coordinate dimension to the specified value.\n" + \
            " -fieldTypeToString type1,...: Converts fields of specified types to\n" + \
            "      fields of type string in the new layer. Valid types are : \n" + \
            "      Integer, Real, String, Date, Time, DateTime, Binary, IntegerList, RealList,\n" + \
            "      StringList. Special value All can be used to convert all fields to strings.")

    print(" -a_srs srs_def: Assign an output SRS\n"
        " -t_srs srs_def: Reproject/transform to this SRS on output\n"
        " -s_srs srs_def: Override source SRS\n"
        "\n"
        " Srs_def can be a full WKT definition (hard to escape properly),\n"
        " or a well known definition (i.e. EPSG:4326) or a file with a WKT\n"
        " definition." )

    return False

def CSLFindString(v, mystr):
    i = 0
    for strIter in v:
        if EQUAL(strIter, mystr):
            return i
        i = i + 1
    return -1

def IsNumber( pszStr):
    try:
        (float)(pszStr)
        return True
    except:
        return False

def LoadGeometry( pszDS, pszSQL, pszLyr, pszWhere):
    poGeom = None

    poDS = ogr.Open( pszDS, False )
    if poDS is None:
        return None

    if pszSQL is not None:
        poLyr = poDS.ExecuteSQL( pszSQL, None, None )
    elif pszLyr is not None:
        poLyr = poDS.GetLayerByName(pszLyr)
    else:
        poLyr = poDS.GetLayer(0)

    if poLyr is None:
        print("Failed to identify source layer from datasource.")
        poDS.Destroy()
        return None

    if pszWhere is not None:
        poLyr.SetAttributeFilter(pszWhere)

    poFeat = poLyr.GetNextFeature()
    while poFeat is not None:
        poSrcGeom = poFeat.GetGeometryRef()
        if poSrcGeom is not None:
            eType = wkbFlatten(poSrcGeom.GetGeometryType())

            if poGeom is None:
                poGeom = ogr.Geometry( ogr.wkbMultiPolygon )

            if eType == ogr.wkbPolygon:
                poGeom.AddGeometry( poSrcGeom )
            elif eType == ogr.wkbMultiPolygon:
                for iGeom in range(poSrcGeom.GetGeometryCount()):
                    poGeom.AddGeometry(poSrcGeom.GetGeometryRef(iGeom) )

            else:
                print("ERROR: Geometry not of polygon type." )
                if pszSQL is not None:
                    poDS.ReleaseResultSet( poLyr )
                poDS.Destroy()
                return None

        poFeat = poLyr.GetNextFeature()

    if pszSQL is not None:
        poDS.ReleaseResultSet( poLyr )
    poDS.Destroy()

    return poGeom


def wkbFlatten(x):
    return x & (~ogr.wkb25DBit)

#**********************************************************************
#                               SetZ()
#**********************************************************************

def SetZ (poGeom, dfZ ):

    if poGeom is None:
        return

    eGType = wkbFlatten(poGeom.GetGeometryType())
    if eGType == ogr.wkbPoint:
        poGeom.SetPoint(0, poGeom.GetX(), poGeom.GetY(), dfZ)

    elif eGType == ogr.wkbLineString or \
         eGType == ogr.wkbLinearRing:
        for i in range(poGeom.GetPointCount()):
            poGeom.SetPoint(i, poGeom.GetX(i), poGeom.GetY(i), dfZ)

    elif eGType == ogr.wkbPolygon or \
         eGType == ogr.wkbMultiPoint or \
         eGType == ogr.wkbMultiLineString or \
         eGType == ogr.wkbMultiPolygon or \
         eGType == ogr.wkbGeometryCollection:
        for i in range(poGeom.GetGeometryCount()):
            SetZ(poGeom.GetGeometryRef(i), dfZ)

#**********************************************************************
#                         SetupTargetLayer()
#**********************************************************************

def SetupTargetLayer( poSrcDS, poSrcLayer, poDstDS, papszLCO, pszNewLayerName, \
                    bTransform,  poOutputSRS, bNullifyOutputSRS, poSourceSRS, papszSelFields, \
                    bAppend, eGType, bPromoteToMulti, nCoordDim, bOverwrite, \
                    papszFieldTypesToString, bWrapDateline, \
                    bExplodeCollections, pszZField, pszWHERE) :

    if pszNewLayerName is None:
        pszNewLayerName = poSrcLayer.GetLayerDefn().GetName()

# --------------------------------------------------------------------
#      Setup coordinate transformation if we need it.
# --------------------------------------------------------------------
    poCT = None

    if bTransform:
        if poSourceSRS is None:
            poSourceSRS = poSrcLayer.GetSpatialRef()

        if poSourceSRS is None:
            print("Can't transform coordinates, source layer has no\n" + \
                    "coordinate system.  Use -s_srs to set one." )
            return None

        poCT = osr.CoordinateTransformation( poSourceSRS, poOutputSRS )
        if gdal.GetLastErrorMsg().find( 'Unable to load PROJ.4 library' ) != -1:
            poCT = None

        if poCT is None:
            pszWKT = None

            print("Failed to create coordinate transformation between the\n" + \
                "following coordinate systems.  This may be because they\n" + \
                "are not transformable, or because projection services\n" + \
                "(PROJ.4 DLL/.so) could not be loaded." )

            pszWKT = poSourceSRS.ExportToPrettyWkt( 0 )
            print( "Source:\n" + pszWKT )

            pszWKT = poOutputSRS.ExportToPrettyWkt( 0 )
            print( "Target:\n" + pszWKT )
            return None

# --------------------------------------------------------------------
#      Get other info.
# --------------------------------------------------------------------
    poSrcFDefn = poSrcLayer.GetLayerDefn()

    if poOutputSRS is None and not bNullifyOutputSRS:
        poOutputSRS = poSrcLayer.GetSpatialRef()

# --------------------------------------------------------------------
#      Find the layer.
# --------------------------------------------------------------------

    # GetLayerByName() can instantiate layers that would have been
    # 'hidden' otherwise, for example, non-spatial tables in a
    # PostGIS-enabled database, so this apparently useless command is
    # not useless. (#4012)
    gdal.PushErrorHandler('CPLQuietErrorHandler')
    poDstLayer = poDstDS.GetLayerByName(pszNewLayerName)
    gdal.PopErrorHandler()
    gdal.ErrorReset()

    iLayer = -1
    if poDstLayer is not None:
        nLayerCount = poDstDS.GetLayerCount()
        for iLayer in range(nLayerCount):
            poLayer = poDstDS.GetLayer(iLayer)
            # The .cpp version compares on pointers directly, but we cannot
            # do this with swig object, so just compare the names.
            if poLayer is not None \
                and poLayer.GetName() == poDstLayer.GetName():
                break

        if (iLayer == nLayerCount):
            # Shouldn't happen with an ideal driver
            poDstLayer = None

# --------------------------------------------------------------------
#      If the user requested overwrite, and we have the layer in
#      question we need to delete it now so it will get recreated
#      (overwritten).
# --------------------------------------------------------------------
    if poDstLayer is not None and bOverwrite:
        if poDstDS.DeleteLayer( iLayer ) != 0:
            print("DeleteLayer() failed when overwrite requested." )
            return None

        poDstLayer = None

# --------------------------------------------------------------------
#      If the layer does not exist, then create it.
# --------------------------------------------------------------------
    if poDstLayer is None:
        if eGType == -2:
            eGType = poSrcFDefn.GetGeomType()

            n25DBit = eGType & ogr.wkb25DBit
            if bPromoteToMulti:
                if wkbFlatten(eGType) == ogr.wkbLineString:
                    eGType = ogr.wkbMultiLineString | n25DBit
                elif wkbFlatten(eGType) == ogr.wkbPolygon:
                    eGType = ogr.wkbMultiPolygon | n25DBit

            if bExplodeCollections:
                if wkbFlatten(eGType) == ogr.wkbMultiPoint:
                    eGType = ogr.wkbPoint | n25DBit
                elif wkbFlatten(eGType) == ogr.wkbMultiLineString:
                    eGType = ogr.wkbLineString | n25DBit
                elif wkbFlatten(eGType) == ogr.wkbMultiPolygon:
                    eGType = ogr.wkbPolygon | n25DBit
                elif wkbFlatten(eGType) == ogr.wkbGeometryCollection:
                    eGType = ogr.wkbUnknown | n25DBit

            if pszZField is not None:
                eGType = eGType | ogr.wkb25DBit

        if nCoordDim == 2:
            eGType = eGType & ~ogr.wkb25DBit
        elif nCoordDim == 3:
            eGType = eGType | ogr.wkb25DBit

        if poDstDS.TestCapability( ogr.ODsCCreateLayer ) == False:
            print("Layer " + pszNewLayerName + "not found, and CreateLayer not supported by driver.")
            return None

        gdal.ErrorReset()

        poDstLayer = poDstDS.CreateLayer( pszNewLayerName, poOutputSRS, \
                                            eGType, papszLCO )

        if poDstLayer is None:
            return None

        bAppend = False

# --------------------------------------------------------------------
#      Otherwise we will append to it, if append was requested.
# --------------------------------------------------------------------
    elif not bAppend:
        print("FAILED: Layer " + pszNewLayerName + "already exists, and -append not specified.\n" + \
                            "        Consider using -append, or -overwrite.")
        return None
    else:
        if len(papszLCO) > 0:
            print("WARNING: Layer creation options ignored since an existing layer is\n" + \
                    "         being appended to." )

# --------------------------------------------------------------------
#      Add fields.  Default to copy all field.
#      If only a subset of all fields requested, then output only
#      the selected fields, and in the order that they were
#      selected.
# --------------------------------------------------------------------

    # Initialize the index-to-index map to -1's
    nSrcFieldCount = poSrcFDefn.GetFieldCount()
    panMap = [ -1 for i in range(nSrcFieldCount) ]

    poDstFDefn = poDstLayer.GetLayerDefn()

    if papszSelFields is not None and not bAppend:

        nDstFieldCount = 0
        if poDstFDefn is not None:
            nDstFieldCount = poDstFDefn.GetFieldCount()

        for iField in range(len(papszSelFields)):

            iSrcField = poSrcFDefn.GetFieldIndex(papszSelFields[iField])
            if iSrcField >= 0:
                poSrcFieldDefn = poSrcFDefn.GetFieldDefn(iSrcField)
                oFieldDefn = ogr.FieldDefn( poSrcFieldDefn.GetNameRef(),
                                            poSrcFieldDefn.GetType() )
                oFieldDefn.SetWidth( poSrcFieldDefn.GetWidth() )
                oFieldDefn.SetPrecision( poSrcFieldDefn.GetPrecision() )

                if papszFieldTypesToString is not None and \
                    (CSLFindString(papszFieldTypesToString, "All") != -1 or \
                    CSLFindString(papszFieldTypesToString, \
                                ogr.GetFieldTypeName(poSrcFieldDefn.GetType())) != -1):

                    oFieldDefn.SetType(ogr.OFTString)

                # The field may have been already created at layer creation
                iDstField = -1
                if poDstFDefn is not None:
                    iDstField = poDstFDefn.GetFieldIndex(oFieldDefn.GetNameRef())
                if iDstField >= 0:
                    panMap[iSrcField] = iDstField
                elif poDstLayer.CreateField( oFieldDefn ) == 0:
                    # now that we've created a field, GetLayerDefn() won't return NULL
                    if poDstFDefn is None:
                        poDstFDefn = poDstLayer.GetLayerDefn()

                    # Sanity check : if it fails, the driver is buggy
                    if poDstFDefn is not None and \
                        poDstFDefn.GetFieldCount() != nDstFieldCount + 1:
                        print("The output driver has claimed to have added the %s field, but it did not!" %  oFieldDefn.GetNameRef() )
                    else:
                        panMap[iSrcField] = nDstFieldCount
                        nDstFieldCount = nDstFieldCount + 1

            else:
                print("Field '" + papszSelFields[iField] + "' not found in source layer.")
                if not bSkipFailures:
                    return None

        # --------------------------------------------------------------------
        # Use SetIgnoredFields() on source layer if available
        # --------------------------------------------------------------------

        # Here we differ from the ogr2ogr.cpp implementation since the OGRFeatureQuery
        # isn't mapped to swig. So in that case just don't use SetIgnoredFields()
        # to avoid issue raised in #4015
        if poSrcLayer.TestCapability(ogr.OLCIgnoreFields) and pszWHERE is None:
            papszIgnoredFields = []
            for iSrcField in range(nSrcFieldCount):
                pszFieldName = poSrcFDefn.GetFieldDefn(iSrcField).GetNameRef()
                bFieldRequested = False
                for iField in range(len(papszSelFields)):
                    if EQUAL(pszFieldName, papszSelFields[iField]):
                        bFieldRequested = True
                        break

                if pszZField is not None and EQUAL(pszFieldName, pszZField):
                    bFieldRequested = True

                # If source field not requested, add it to ignored files list
                if not bFieldRequested:
                    papszIgnoredFields.append(pszFieldName)

            poSrcLayer.SetIgnoredFields(papszIgnoredFields)

    elif not bAppend:

        nDstFieldCount = 0
        if poDstFDefn is not None:
            nDstFieldCount = poDstFDefn.GetFieldCount()

        for iField in range(nSrcFieldCount):

            poSrcFieldDefn = poSrcFDefn.GetFieldDefn(iField)
            oFieldDefn = ogr.FieldDefn( poSrcFieldDefn.GetNameRef(),
                                        poSrcFieldDefn.GetType() )
            oFieldDefn.SetWidth( poSrcFieldDefn.GetWidth() )
            oFieldDefn.SetPrecision( poSrcFieldDefn.GetPrecision() )

            if papszFieldTypesToString is not None and \
                (CSLFindString(papszFieldTypesToString, "All") != -1 or \
                CSLFindString(papszFieldTypesToString, \
                            ogr.GetFieldTypeName(poSrcFieldDefn.GetType())) != -1):

                oFieldDefn.SetType(ogr.OFTString)

            # The field may have been already created at layer creation
            iDstField = -1
            if poDstFDefn is not None:
                 iDstField = poDstFDefn.GetFieldIndex(oFieldDefn.GetNameRef())
            if iDstField >= 0:
                panMap[iField] = iDstField
            elif poDstLayer.CreateField( oFieldDefn ) == 0:
                # now that we've created a field, GetLayerDefn() won't return NULL
                if poDstFDefn is None:
                    poDstFDefn = poDstLayer.GetLayerDefn()

                # Sanity check : if it fails, the driver is buggy
                if poDstFDefn is not None and \
                    poDstFDefn.GetFieldCount() != nDstFieldCount + 1:
                    print("The output driver has claimed to have added the %s field, but it did not!" %  oFieldDefn.GetNameRef() )
                else:
                    panMap[iField] = nDstFieldCount
                    nDstFieldCount = nDstFieldCount + 1

    else:
        # For an existing layer, build the map by fetching the index in the destination
        # layer for each source field
        if poDstFDefn is None:
            print( "poDstFDefn == NULL.\n" )
            return None

        for iField in range(nSrcFieldCount):
            poSrcFieldDefn = poSrcFDefn.GetFieldDefn(iField)
            iDstField = poDstFDefn.GetFieldIndex(poSrcFieldDefn.GetNameRef())
            if iDstField >= 0:
                panMap[iField] = iDstField

    iSrcZField = -1
    if pszZField is not None:
        iSrcZField = poSrcFDefn.GetFieldIndex(pszZField)

    psInfo = TargetLayerInfo()
    psInfo.poDstLayer = poDstLayer
    psInfo.poCT = poCT
    #psInfo.papszTransformOptions = papszTransformOptions
    psInfo.panMap = panMap
    psInfo.iSrcZField = iSrcZField

    return psInfo

#**********************************************************************
#                           TranslateLayer()
#**********************************************************************

def TranslateLayer( psInfo, poSrcDS, poSrcLayer, poDstDS,  \
                    poOutputSRS, bNullifyOutputSRS, \
                    eGType, bPromoteToMulti, nCoordDim, eGeomOp, dfGeomOpParam, \
                    nCountLayerFeatures, \
                    poClipSrc, poClipDst, bExplodeCollections, nSrcFileSize, \
                    pnReadFeatureCount, pfnProgress, pProgressArg) :

    bForceToPolygon = False
    bForceToMultiPolygon = False
    bForceToMultiLineString = False

    poDstLayer = psInfo.poDstLayer
    #papszTransformOptions = psInfo.papszTransformOptions
    poCT = psInfo.poCT
    panMap = psInfo.panMap
    iSrcZField = psInfo.iSrcZField

    if poOutputSRS is None and not bNullifyOutputSRS:
        poOutputSRS = poSrcLayer.GetSpatialRef()

    if wkbFlatten(eGType) == ogr.wkbPolygon:
        bForceToPolygon = True
    elif wkbFlatten(eGType) == ogr.wkbMultiPolygon:
        bForceToMultiPolygon = True
    elif wkbFlatten(eGType) == ogr.wkbMultiLineString:
        bForceToMultiLineString = True

# --------------------------------------------------------------------
#      Transfer features.
# --------------------------------------------------------------------
    nFeaturesInTransaction = 0
    nCount = 0

    if nGroupTransactions > 0:
        poDstLayer.StartTransaction()

    while True:
        poDstFeature = None

        if nFIDToFetch != ogr.NullFID:

            #// Only fetch feature on first pass.
            if nFeaturesInTransaction == 0:
                poFeature = poSrcLayer.GetFeature(nFIDToFetch)
            else:
                poFeature = None

        else:
            poFeature = poSrcLayer.GetNextFeature()

        if poFeature is None:
            break

        nParts = 0
        nIters = 1
        if bExplodeCollections:
            poSrcGeometry = poFeature.GetGeometryRef()
            if poSrcGeometry is not None:
                eSrcType = wkbFlatten(poSrcGeometry.GetGeometryType())
                if eSrcType == ogr.wkbMultiPoint or \
                   eSrcType == ogr.wkbMultiLineString or \
                   eSrcType == ogr.wkbMultiPolygon or \
                   eSrcType == ogr.wkbGeometryCollection:
                        nParts = poSrcGeometry.GetGeometryCount()
                        nIters = nParts
                        if nIters == 0:
                            nIters = 1

        for iPart in range(nIters):
            nFeaturesInTransaction = nFeaturesInTransaction + 1
            if nFeaturesInTransaction == nGroupTransactions:
                poDstLayer.CommitTransaction()
                poDstLayer.StartTransaction()
                nFeaturesInTransaction = 0

            gdal.ErrorReset()
            poDstFeature = ogr.Feature( poDstLayer.GetLayerDefn() )

            if poDstFeature.SetFromWithMap( poFeature, 1, panMap ) != 0:

                if nGroupTransactions > 0:
                    poDstLayer.CommitTransaction()

                print("Unable to translate feature %d from layer %s" % (poFeature.GetFID() , poSrcLayer.GetName() ))

                return False

            if bPreserveFID:
                poDstFeature.SetFID( poFeature.GetFID() )

            poDstGeometry = poDstFeature.GetGeometryRef()
            if poDstGeometry is not None:

                if nParts > 0:
                    # For -explodecollections, extract the iPart(th) of the geometry
                    poPart = poDstGeometry.GetGeometryRef(iPart).Clone()
                    poDstFeature.SetGeometryDirectly(poPart)
                    poDstGeometry = poPart

                if iSrcZField != -1:
                    SetZ(poDstGeometry, poFeature.GetFieldAsDouble(iSrcZField))
                    # This will correct the coordinate dimension to 3
                    poDupGeometry = poDstGeometry.Clone()
                    poDstFeature.SetGeometryDirectly(poDupGeometry)
                    poDstGeometry = poDupGeometry


                if nCoordDim == 2 or nCoordDim == 3:
                    poDstGeometry.SetCoordinateDimension( nCoordDim )

                if eGeomOp == GeomOperation.SEGMENTIZE:
                    pass
                    #if (poDstFeature.GetGeometryRef() is not None and dfGeomOpParam > 0)
                    #    poDstFeature.GetGeometryRef().segmentize(dfGeomOpParam);
                elif eGeomOp == GeomOperation.SIMPLIFY_PRESERVE_TOPOLOGY and dfGeomOpParam > 0:
                    poNewGeom = poDstGeometry.SimplifyPreserveTopology(dfGeomOpParam)
                    if poNewGeom is not None:
                        poDstFeature.SetGeometryDirectly(poNewGeom)
                        poDstGeometry = poNewGeom

                if poClipSrc is not None:
                    poClipped = poDstGeometry.Intersection(poClipSrc)
                    if poClipped is None or poClipped.IsEmpty():
                        # Report progress
                        nCount = nCount +1
                        if pfnProgress is not None:
                            pfnProgress(nCount * 1.0 / nCountLayerFeatures, "", pProgressArg)
                        continue

                    poDstFeature.SetGeometryDirectly(poClipped)
                    poDstGeometry = poClipped

                if poCT is not None:
                    eErr = poDstGeometry.Transform( poCT )
                    if eErr != 0:
                        if nGroupTransactions > 0:
                            poDstLayer.CommitTransaction()

                        print("Failed to reproject feature %d (geometry probably out of source or destination SRS)." % poFeature.GetFID())
                        if not bSkipFailures:
                            return False

                elif poOutputSRS is not None:
                    poDstGeometry.AssignSpatialReference(poOutputSRS)

                if poClipDst is not None:
                    poClipped = poDstGeometry.Intersection(poClipDst)
                    if poClipped is None or poClipped.IsEmpty():
                        continue

                    poDstFeature.SetGeometryDirectly(poClipped)
                    poDstGeometry = poClipped

                if bForceToPolygon:
                    poDstFeature.SetGeometryDirectly(ogr.ForceToPolygon(poDstGeometry))

                elif bForceToMultiPolygon or \
                        (bPromoteToMulti and wkbFlatten(poDstGeometry.GetGeometryType()) == ogr.wkbPolygon):
                    poDstFeature.SetGeometryDirectly(ogr.ForceToMultiPolygon(poDstGeometry))

                elif bForceToMultiLineString or \
                        (bPromoteToMulti and wkbFlatten(poDstGeometry.GetGeometryType()) == ogr.wkbLineString):
                    poDstFeature.SetGeometryDirectly(ogr.ForceToMultiLineString(poDstGeometry))

            gdal.ErrorReset()
            if poDstLayer.CreateFeature( poDstFeature ) != 0 and not bSkipFailures:
                if nGroupTransactions > 0:
                    poDstLayer.RollbackTransaction()

                return False

        # Report progress
        nCount = nCount  + 1
        if pfnProgress is not None:
            if nSrcFileSize != 0:
                if (nCount % 1000) == 0:
                    poFCLayer = poSrcDS.ExecuteSQL("GetBytesRead()", None, None)
                    if poFCLayer is not None:
                        poFeat = poFCLayer.GetNextFeature()
                        if poFeat is not None:
                            pszReadSize = poFeat.GetFieldAsString(0)
                            nReadSize = int(pszReadSize)
                            pfnProgress(nReadSize * 1.0 / nSrcFileSize, "", pProgressArg)
                    poSrcDS.ReleaseResultSet(poFCLayer)
            else:
                pfnProgress(nCount * 1.0 / nCountLayerFeatures, "", pProgressArg)

        if pnReadFeatureCount is not None:
            pnReadFeatureCount[0] = nCount

    if nGroupTransactions > 0:
        poDstLayer.CommitTransaction()

    return True

if __name__ == '__main__':
    version_num = int(gdal.VersionInfo('VERSION_NUM'))
    if version_num < 1800: # because of ogr.GetFieldTypeName
        print('ERROR: Python bindings of GDAL 1.8.0 or later required')
        sys.exit(1)

    if not main(sys.argv):
        sys.exit(1)
    else:
        sys.exit(0)


More information about the Africa mailing list