mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-27 00:33:48 -05:00
parameter to that type - change default level to WARNING - change startup messages to INFO - don't unhide the warning button for INFO messages - fix warnings produced by python code
1612 lines
61 KiB
Python
1612 lines
61 KiB
Python
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
|
|
"""
|
|
***************************************************************************
|
|
ogr2ogr.py
|
|
---------------------
|
|
Date : November 2012
|
|
Copyright : (C) 2012 by Victor Olaya
|
|
Email : volayaf at gmail dot com
|
|
***************************************************************************
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
***************************************************************************
|
|
"""
|
|
|
|
__author__ = 'Victor Olaya'
|
|
__date__ = 'November 2012'
|
|
__copyright__ = '(C) 2012, Victor Olaya'
|
|
# This will get replaced with a git SHA1 when you do a git archive
|
|
__revision__ = '$Format:%H$'
|
|
|
|
# Based on ogr2ogr.py implementation by Even Rouault included in GDAL/OGR
|
|
|
|
import sys
|
|
import os
|
|
import stat
|
|
|
|
try:
|
|
from osgeo import gdal, ogr, osr
|
|
gdalAvailable = True
|
|
except:
|
|
gdalAvailable = False
|
|
|
|
###############################################################################
|
|
|
|
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 StdStreamCapture(object):
|
|
def __init__(self, outputfunc=None):
|
|
self._outputfunc = outputfunc
|
|
|
|
def __enter__(self):
|
|
if self._outputfunc is not None:
|
|
self._old_stdout = sys.stdout
|
|
self._old_stdout.flush()
|
|
self._old_stderr = sys.stderr
|
|
self._old_stderr.flush()
|
|
sys.stdout = sys.stderr = self
|
|
|
|
def __exit__(self, exc_type, exc_value, traceback):
|
|
if self._outputfunc is not None:
|
|
sys.stdout.flush()
|
|
sys.stdout = self._old_stdout
|
|
sys.stderr.flush()
|
|
sys.stderr = self._old_stderr
|
|
|
|
#Stream methods
|
|
|
|
def write(self, s):
|
|
self._outputfunc(s)
|
|
|
|
def flush(self):
|
|
pass
|
|
|
|
|
|
#/************************************************************************/
|
|
#/* main() */
|
|
#/************************************************************************/
|
|
|
|
bSkipFailures = False
|
|
nGroupTransactions = 200
|
|
bPreserveFID = False
|
|
nFIDToFetch = ogr.NullFID if gdalAvailable else None
|
|
|
|
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
|
|
poSourceSRS = None
|
|
pszNewLayerName = None
|
|
pszWHERE = None
|
|
poSpatialFilter = None
|
|
pszSelect = None
|
|
papszSelFields = None
|
|
pszSQLStatement = None
|
|
eGType = -2
|
|
eGeomOp = GeomOperation.NONE
|
|
dfGeomOpParam = 0
|
|
papszFieldTypesToString = []
|
|
bDisplayProgress = False
|
|
bClipSrc = 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
|
|
bExplodeCollections = False
|
|
pszZField = None
|
|
|
|
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], "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], "-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]
|
|
|
|
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()
|
|
|
|
return ogr2ogr(
|
|
pszFormat,
|
|
pszDataSource,
|
|
pszDestDataSource,
|
|
papszLayers,
|
|
papszDSCO,
|
|
papszLCO,
|
|
bTransform,
|
|
bAppend,
|
|
bUpdate,
|
|
bOverwrite,
|
|
pszOutputSRSDef,
|
|
pszSourceSRSDef,
|
|
poOutputSRS,
|
|
poSourceSRS,
|
|
pszNewLayerName,
|
|
pszWHERE,
|
|
poSpatialFilter,
|
|
pszSelect,
|
|
papszSelFields,
|
|
pszSQLStatement,
|
|
eGType,
|
|
eGeomOp,
|
|
dfGeomOpParam,
|
|
papszFieldTypesToString,
|
|
bDisplayProgress,
|
|
progress_func,
|
|
progress_data,
|
|
bClipSrc,
|
|
poClipSrc,
|
|
pszClipSrcDS,
|
|
pszClipSrcSQL,
|
|
pszClipSrcLayer,
|
|
pszClipSrcWhere,
|
|
poClipDst,
|
|
pszClipDstDS,
|
|
pszClipDstSQL,
|
|
pszClipDstLayer,
|
|
pszClipDstWhere,
|
|
pszSrcEncoding,
|
|
pszDstEncoding,
|
|
bExplodeCollections,
|
|
pszZField)
|
|
|
|
def ogr2ogr(
|
|
pszFormat="ESRI Shapefile",
|
|
pszDataSource=None,
|
|
pszDestDataSource=None,
|
|
papszLayers=[],
|
|
papszDSCO=[],
|
|
papszLCO=[],
|
|
bTransform=False,
|
|
bAppend=False,
|
|
bUpdate=False,
|
|
bOverwrite=False,
|
|
pszOutputSRSDef=None,
|
|
pszSourceSRSDef=None,
|
|
poOutputSRS=None,
|
|
poSourceSRS=None,
|
|
pszNewLayerName=None,
|
|
pszWHERE=None,
|
|
poSpatialFilter=None,
|
|
pszSelect=None,
|
|
papszSelFields=None,
|
|
pszSQLStatement=None,
|
|
eGType= -2,
|
|
eGeomOp=GeomOperation.NONE,
|
|
dfGeomOpParam=0,
|
|
papszFieldTypesToString=[],
|
|
bDisplayProgress=False,
|
|
progress_func=None,
|
|
progress_data=None,
|
|
bClipSrc=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,
|
|
bExplodeCollections=False,
|
|
pszZField=None,
|
|
errfunc=None):
|
|
# Redirect Stdout & Stderr to error function
|
|
with StdStreamCapture(errfunc):
|
|
return ogr2ogrStdstreams(
|
|
pszFormat,
|
|
pszDataSource,
|
|
pszDestDataSource,
|
|
papszLayers,
|
|
papszDSCO,
|
|
papszLCO,
|
|
bTransform,
|
|
bAppend,
|
|
bUpdate,
|
|
bOverwrite,
|
|
pszOutputSRSDef,
|
|
pszSourceSRSDef,
|
|
poOutputSRS,
|
|
poSourceSRS,
|
|
pszNewLayerName,
|
|
pszWHERE,
|
|
poSpatialFilter,
|
|
pszSelect,
|
|
papszSelFields,
|
|
pszSQLStatement,
|
|
eGType,
|
|
eGeomOp,
|
|
dfGeomOpParam,
|
|
papszFieldTypesToString,
|
|
bDisplayProgress,
|
|
progress_func,
|
|
progress_data,
|
|
bClipSrc,
|
|
poClipSrc,
|
|
pszClipSrcDS,
|
|
pszClipSrcSQL,
|
|
pszClipSrcLayer,
|
|
pszClipSrcWhere,
|
|
poClipDst,
|
|
pszClipDstDS,
|
|
pszClipDstSQL,
|
|
pszClipDstLayer,
|
|
pszClipDstWhere,
|
|
pszSrcEncoding,
|
|
pszDstEncoding,
|
|
bExplodeCollections,
|
|
pszZField)
|
|
|
|
def ogr2ogrStdstreams(
|
|
pszFormat="ESRI Shapefile",
|
|
pszDataSource=None,
|
|
pszDestDataSource=None,
|
|
papszLayers=[],
|
|
papszDSCO=[],
|
|
papszLCO=[],
|
|
bTransform=False,
|
|
bAppend=False,
|
|
bUpdate=False,
|
|
bOverwrite=False,
|
|
pszOutputSRSDef=None,
|
|
pszSourceSRSDef=None,
|
|
poOutputSRS=None,
|
|
poSourceSRS=None,
|
|
pszNewLayerName=None,
|
|
pszWHERE=None,
|
|
poSpatialFilter=None,
|
|
pszSelect=None,
|
|
papszSelFields=None,
|
|
pszSQLStatement=None,
|
|
eGType= -2,
|
|
eGeomOp=GeomOperation.NONE,
|
|
dfGeomOpParam=0,
|
|
papszFieldTypesToString=[],
|
|
bDisplayProgress=False,
|
|
progress_func=None,
|
|
progress_data=None,
|
|
bClipSrc=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,
|
|
bExplodeCollections=False,
|
|
pszZField=None):
|
|
|
|
pfnProgress = None
|
|
pProgressData = None
|
|
|
|
#/* -------------------------------------------------------------------- */
|
|
#/* Open data source. */
|
|
#/* -------------------------------------------------------------------- */
|
|
if isinstance(pszDataSource, str):
|
|
poDS = ogr.Open(pszDataSource, False)
|
|
else:
|
|
poDS = pszDataSource
|
|
|
|
#/* -------------------------------------------------------------------- */
|
|
#/* 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:
|
|
# /* ok 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
|
|
|
|
#/* -------------------------------------------------------------------- */
|
|
#/* 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 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
|
|
pProgressData = 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
|
|
|
|
if not TranslateLayer(poDS, poResultSet, poODS, papszLCO, \
|
|
pszNewLayerName, bTransform, poOutputSRS, \
|
|
poSourceSRS, papszSelFields, bAppend, eGType, \
|
|
bOverwrite, eGeomOp, dfGeomOpParam, papszFieldTypesToString, \
|
|
nCountLayerFeatures, poClipSrc, poClipDst, bExplodeCollections, \
|
|
pszZField, pszWHERE, pfnProgress, pProgressData):
|
|
print(
|
|
"Terminating translation prematurely after failed\n" + \
|
|
"translation from sql statement.")
|
|
|
|
return False
|
|
|
|
poDS.ReleaseResultSet(poResultSet)
|
|
|
|
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("FAILURE: 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:
|
|
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]
|
|
|
|
#print(poLayer.GetLayerDefn().GetName()) #debugging
|
|
|
|
if bDisplayProgress:
|
|
pfnProgress = ScaledProgressFunc
|
|
pProgressData = 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
|
|
|
|
if not TranslateLayer(poDS, poLayer, poODS, papszLCO, \
|
|
pszNewLayerName, bTransform, poOutputSRS, \
|
|
poSourceSRS, papszSelFields, bAppend, eGType, \
|
|
bOverwrite, eGeomOp, dfGeomOpParam, papszFieldTypesToString, \
|
|
panLayerCountFeatures[iLayer], poClipSrc, poClipDst, bExplodeCollections, \
|
|
pszZField, pszWHERE, pfnProgress, pProgressData) \
|
|
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 explicetely 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] [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" + \
|
|
" -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 (ie. 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)
|
|
|
|
#/************************************************************************/
|
|
#/* TranslateLayer() */
|
|
#/************************************************************************/
|
|
|
|
def TranslateLayer(poSrcDS, poSrcLayer, poDstDS, papszLCO, pszNewLayerName, \
|
|
bTransform, poOutputSRS, poSourceSRS, papszSelFields, \
|
|
bAppend, eGType, bOverwrite, eGeomOp, dfGeomOpParam, \
|
|
papszFieldTypesToString, nCountLayerFeatures, \
|
|
poClipSrc, poClipDst, bExplodeCollections, pszZField, pszWHERE, \
|
|
pfnProgress, pProgressData) :
|
|
|
|
bForceToPolygon = False
|
|
bForceToMultiPolygon = False
|
|
bForceToMultiLineString = False
|
|
|
|
if pszNewLayerName is None:
|
|
pszNewLayerName = poSrcLayer.GetLayerDefn().GetName()
|
|
|
|
if wkbFlatten(eGType) == ogr.wkbPolygon:
|
|
bForceToPolygon = True
|
|
elif wkbFlatten(eGType) == ogr.wkbMultiPolygon:
|
|
bForceToMultiPolygon = True
|
|
elif wkbFlatten(eGType) == ogr.wkbMultiLineString:
|
|
bForceToMultiLineString = True
|
|
|
|
#/* -------------------------------------------------------------------- */
|
|
#/* 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 False
|
|
|
|
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 False
|
|
|
|
#/* -------------------------------------------------------------------- */
|
|
#/* Get other info. */
|
|
#/* -------------------------------------------------------------------- */
|
|
poSrcFDefn = poSrcLayer.GetLayerDefn()
|
|
|
|
if poOutputSRS is None:
|
|
poOutputSRS = poSrcLayer.GetSpatialRef()
|
|
|
|
#/* -------------------------------------------------------------------- */
|
|
#/* Find the layer. */
|
|
#/* -------------------------------------------------------------------- */
|
|
|
|
#/* GetLayerByName() can instanciate 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 False
|
|
|
|
poDstLayer = None
|
|
|
|
#/* -------------------------------------------------------------------- */
|
|
#/* If the layer does not exist, then create it. */
|
|
#/* -------------------------------------------------------------------- */
|
|
if poDstLayer is None:
|
|
if eGType == -2:
|
|
eGType = poSrcFDefn.GetGeomType()
|
|
|
|
if bExplodeCollections:
|
|
n25DBit = eGType & ogr.wkb25DBit
|
|
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 poDstDS.TestCapability(ogr.ODsCCreateLayer) == False:
|
|
print("Layer " + pszNewLayerName + "not found, and CreateLayer not supported by driver.")
|
|
return False
|
|
|
|
gdal.ErrorReset()
|
|
|
|
poDstLayer = poDstDS.CreateLayer(pszNewLayerName, poOutputSRS, \
|
|
eGType, papszLCO)
|
|
|
|
if poDstLayer is None:
|
|
return False
|
|
|
|
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 False
|
|
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 False
|
|
|
|
#/* -------------------------------------------------------------------- */
|
|
#/* 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 False
|
|
|
|
for iField in range(nSrcFieldCount):
|
|
poSrcFieldDefn = poSrcFDefn.GetFieldDefn(iField)
|
|
iDstField = poDstFDefn.GetFieldIndex(poSrcFieldDefn.GetNameRef())
|
|
if iDstField >= 0:
|
|
panMap[iField] = iDstField
|
|
|
|
#/* -------------------------------------------------------------------- */
|
|
#/* Transfer features. */
|
|
#/* -------------------------------------------------------------------- */
|
|
nFeaturesInTransaction = 0
|
|
nCount = 0
|
|
|
|
iSrcZField = -1
|
|
if pszZField is not None:
|
|
iSrcZField = poSrcFDefn.GetFieldIndex(pszZField)
|
|
|
|
poSrcLayer.ResetReading()
|
|
|
|
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() , poSrcFDefn.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 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, "", pProgressData)
|
|
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():
|
|
#/* Report progress */
|
|
nCount = nCount + 1
|
|
if pfnProgress is not None:
|
|
pfnProgress(nCount * 1.0 / nCountLayerFeatures, "", pProgressData)
|
|
continue
|
|
|
|
poDstFeature.SetGeometryDirectly(poClipped)
|
|
poDstGeometry = poClipped
|
|
|
|
if bForceToPolygon:
|
|
poDstFeature.SetGeometryDirectly(ogr.ForceToPolygon(poDstGeometry))
|
|
|
|
elif bForceToMultiPolygon:
|
|
poDstFeature.SetGeometryDirectly(ogr.ForceToMultiPolygon(poDstGeometry))
|
|
|
|
elif bForceToMultiLineString:
|
|
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:
|
|
pfnProgress(nCount * 1.0 / nCountLayerFeatures, "", pProgressData)
|
|
|
|
if nGroupTransactions > 0:
|
|
poDstLayer.CommitTransaction()
|
|
|
|
return True
|
|
|
|
if __name__ == '__main__':
|
|
if not gdalAvailable:
|
|
print('ERROR: Python bindings of GDAL 1.8.0 or later required')
|
|
|
|
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)
|
|
|