Python GDAL/OGR Vector layer operation
目录
From: https://pcjericks.github.io/py-gdalogr-cookbook/vector_layers.html
目录
Get List of Ogr Drivers Alphabetically (A- Z)
Is Ogr Driver Available by Driver Name
Get All PostGIS layers in a PostgreSQL Database
Get PostGIS Layer Feature Count By Layer Name
Get all layers in an Esri File GeoDataBase
Get Geometry from each Feature in a Layer
Get Shapefile Fields – Get the user defined fields
Get Shapefile Fields and Types – Get the user defined fields
Get PostGIS Layer Fields – Get the user defined fields
Get PostGIS Layer Fields and Types – Get the user defined fields
Get WFS layers and iterate over features
Set HTTP Proxy options before fetching a web datasource
Read a CSV of Coordinates as an OGRVRTLayer
Create a new Layer from the extent of an existing Layer
Save the convex hull of all geometry from an input Layer to an output Layer
Save centroids of input Layer to an output Layer
Create a New Shapefile and Add Data
Create a PostGIS table from WKT
Filter and Select Input Shapefile to New Output Shapefile Like ogr2ogr CLI
Get a list of the street names in a OSM file
Convert polygon shapefile to line shapefile
Create point shapefile with attribute data
Delete a file
from osgeo import ogr import os DriverName = "ESRI Shapefile" # e.g.: GeoJSON, ESRI Shapefile FileName = 'test.shp' driver = ogr.GetDriverByName(DriverName) if os.path.exists(FileName): driver.DeleteDataSource(FileName)
Is Ogr Installed
try: from osgeo import ogr print 'Import of ogr from osgeo worked. Hurray!\n' except: print 'Import of ogr from osgeo failed\n\n'
View Auto Generated Ogr Help
This code simply prints out the auto-generated help on the imported module. In this case it’s OGR. This might not be the best way to scan the API’s class methods. For a detailed description of the whole Python GDAL/OGR API, see the useful API docs.
import osgeo.ogr print help(osgeo.ogr)
Get List of Ogr Drivers Alphabetically (A- Z)
It’s always driven me a little nuts that the command line ogr2ogr –formats returns a ‘random’ list of drivers. This code returns the list of OGR drivers alphabetically from A – Z. .
import ogr cnt = ogr.GetDriverCount() formatsList = [] # Empty List for i in range(cnt): driver = ogr.GetDriver(i) driverName = driver.GetName() if not driverName in formatsList: formatsList.append(driverName) formatsList.sort() # Sorting the messy list of ogr drivers for i in formatsList: print i
Is Ogr Driver Available by Driver Name
This code shows if a particular OGR driver is available. The exact names are the ones used on the OGR VectorFormats page in the “Code” column ([formats website]). This is the same names returned when you enter
ogrinfo--formats
on the command line.Code Example Source: [website]
from osgeo import ogr ## Shapefile available? driverName = "ESRI Shapefile" drv = ogr.GetDriverByName( driverName ) if drv is None: print "%s driver not available.\n" % driverName else: print "%s driver IS available.\n" % driverName ## PostgreSQL available? driverName = "PostgreSQL" drv = ogr.GetDriverByName( driverName ) if drv is None: print "%s driver not available.\n" % driverName else: print "%s driver IS available.\n" % driverName ## Is File GeoDatabase available? driverName = "FileGDB" drv = ogr.GetDriverByName( driverName ) if drv is None: print "%s driver not available.\n" % driverName else: print "%s driver IS available.\n" % driverName ## SDE available? driverName = "SDE" drv = ogr.GetDriverByName( driverName ) if drv is None: print "%s driver not available.\n" % driverName else: print "%s driver IS available.\n" % driverName
Force Ogr Use Named Driver
Use only the specified driver to attempt to read the data file, taking into account special nature of the CSV driver which normally requires a .csv extension.
Source, Luke Pinner on GIS Stack Exchange: [website]
import sys from osgeo import ogr def main(in_file, in_format, out_file, out_format): if in_format == 'CSV' and in_file[-3:].lower() != 'csv': in_file = 'CSV:' + in_file in_ds = ogr.GetDriverByName(in_format).Open(in_file) out_ds = ogr.GetDriverByName(out_format).CopyDataSource(in_ds, out_file) if __name__ == '__main__': main(*sys.argv[1:])
Usage:
python ogr-convert.py [in file] [format driver] [out file/dir] {out format}
python ogr-convert.py x:incomingcoolstuff.txt CSV d:shapefiles
Get Shapefile Feature Count
This code example opens a shapefile and returns the number of features in it. Solution mined from: [web site]
import os from osgeo import ogr daShapefile = r"C:\Temp\Voting_Centers_and_Ballot_Sites.shp" driver = ogr.GetDriverByName('ESRI Shapefile') dataSource = driver.Open(daShapefile, 0) # 0 means read-only. 1 means writeable. # Check to see if shapefile is found. if dataSource is None: print 'Could not open %s' % (daShapefile) else: print 'Opened %s' % (daShapefile) layer = dataSource.GetLayer() featureCount = layer.GetFeatureCount() print "Number of features in %s: %d" % (os.path.basename(daShapefile),featureCount)
Get All PostGIS layers in a PostgreSQL Database
This returns all the layers in a database of your choosing sorted in alphabetical order (of course). Just fill in the missing information and it should work.
from osgeo import ogr databaseServer = "<IP of database server OR Name of database server" databaseName = "<Name of database>" databaseUser = "<User name>" databasePW = "<User password>" connString = "PG: host=%s dbname=%s user=%s password=%s" %(databaseServer,databaseName,databaseUser,databasePW) conn = ogr.Open(connString) layerList = [] for i in conn: daLayer = i.GetName() if not daLayer in layerList: layerList.append(daLayer) layerList.sort() for j in layerList: print j # Close connection conn = None
Get PostGIS Layer Feature Count By Layer Name
This code example opens a postgis connection and gets the specified layer name if it exists in the database. Otherwise it throws a nice error message
from osgeo import ogr import sys databaseServer = "<IP of database server OR Name of database server" databaseName = "<Name of database>" databaseUser = "<User name>" databasePW = "<User password>" connString = "PG: host=%s dbname=%s user=%s password=%s" % (databaseServer,databaseName,databaseUser,databasePW) def GetPGLayer( lyr_name ): conn = ogr.Open(connString) lyr = conn.GetLayer( lyr_name ) if lyr is None: print >> sys.stderr, '[ ERROR ]: layer name = "%s" could not be found in database "%s"' % ( lyr_name, databaseName ) sys.exit( 1 ) featureCount = lyr.GetFeatureCount() print "Number of features in %s: %d" % ( lyr_name , featureCount ) # Close connection conn = None if __name__ == '__main__': if len( sys.argv ) < 2: print >> sys.stderr, '[ ERROR ]: you must pass at least one argument -- the layer name argument' sys.exit( 1 ) lyr_name = sys.argv[1] GetPGLayer( lyr_name )
Get all layers in an Esri File GeoDataBase
This returns all the layers in a Esri FileGDB in alphabetical order (of course). It needs GDAL/OGR 1.11.0 + but not any Esri dependency. That’s the benefit of the OpenFileGDB driver developed by Ewen Rouault relative to the FileGDB driver.
# standard imports import sys # import OGR from osgeo import ogr # use OGR specific exceptions ogr.UseExceptions() # get the driver driver = ogr.GetDriverByName("OpenFileGDB") # opening the FileGDB try: gdb = driver.Open(gdb_path, 0) except Exception, e: print e sys.exit() # list to store layers'names featsClassList = [] # parsing layers by index for featsClass_idx in range(gdb.GetLayerCount()): featsClass = gdb.GetLayerByIndex(featsClass_idx) featsClassList.append(featsClass.GetName()) # sorting featsClassList.sort() # printing for featsClass in featsClassList: print featsClass # clean close del gdb
Load data to memory
This illustrates how to copy a dataset to memory with write access, providing fast data access.
from osgeo import ogr #open an input datasource indriver=ogr.GetDriverByName('SQLite') srcdb = indriver.Open('OUTDATA.sqlite',0) #create an output datasource in memory outdriver=ogr.GetDriverByName('MEMORY') source=outdriver.CreateDataSource('memData') #open the memory datasource with write access tmp=outdriver.Open('memData',1) #copy a layer to memory pipes_mem=source.CopyLayer(srcdb.GetLayer('pipes'),'pipes',['OVERWRITE=YES']) #the new layer can be directly accessed via the handle pipes_mem or as source.GetLayer('pipes'): layer=source.GetLayer('pipes') for feature in layer: feature.SetField('SOMETHING',1)
Iterate over Features
from osgeo import ogr import os shapefile = "states.shp" driver = ogr.GetDriverByName("ESRI Shapefile") dataSource = driver.Open(shapefile, 0) layer = dataSource.GetLayer() for feature in layer: print feature.GetField("STATE_NAME") layer.ResetReading()
You must call ResetReading if you want to start iterating over the layer again.
Get Geometry from each Feature in a Layer
from osgeo import ogr import os shapefile = "states.shp" driver = ogr.GetDriverByName("ESRI Shapefile") dataSource = driver.Open(shapefile, 0) layer = dataSource.GetLayer() for feature in layer: geom = feature.GetGeometryRef() print geom.Centroid().ExportToWkt()
Filter by attribute
from osgeo import ogr import os shapefile = "states.shp" driver = ogr.GetDriverByName("ESRI Shapefile") dataSource = driver.Open(shapefile, 0) layer = dataSource.GetLayer() layer.SetAttributeFilter("SUB_REGION = 'Pacific'") for feature in layer: print feature.GetField("STATE_NAME")
Spatial Filter
from osgeo import ogr import os shapefile = "states.shp" driver = ogr.GetDriverByName("ESRI Shapefile") dataSource = driver.Open(shapefile, 0) layer = dataSource.GetLayer() wkt = "POLYGON ((-103.81402655265633 50.253951270672125,-102.94583419409656 51.535568561879401,-100.34125711841725 51.328856095555651,-100.34125711841725 51.328856095555651,-93.437060743203844 50.460663736995883,-93.767800689321859 46.450441890315041,-94.635993047881612 41.613370178339181,-100.75468205106476 41.365315218750681,-106.12920617548238 42.564247523428456,-105.96383620242338 47.277291755610058,-103.81402655265633 50.253951270672125))" layer.SetSpatialFilter(ogr.CreateGeometryFromWkt(wkt)) for feature in layer: print feature.GetField("STATE_NAME")
Get Shapefile Fields – Get the user defined fields
This code example returns the field names of the user defined (created) fields.
from osgeo import ogr daShapefile = r"C:\Temp\Voting_Centers_and_Ballot_Sites.shp" dataSource = ogr.Open(daShapefile) daLayer = dataSource.GetLayer(0) layerDefinition = daLayer.GetLayerDefn() for i in range(layerDefinition.GetFieldCount()): print layerDefinition.GetFieldDefn(i).GetName()
Get Shapefile Fields and Types – Get the user defined fields
This code example returns the field names of the user defined (created) fields and the data types they are.
from osgeo import ogr daShapefile = r"C:\Temp\iDay\CWI_Wetlands.shp" dataSource = ogr.Open(daShapefile) daLayer = dataSource.GetLayer(0) layerDefinition = daLayer.GetLayerDefn() print "Name - Type Width Precision" for i in range(layerDefinition.GetFieldCount()): fieldName = layerDefinition.GetFieldDefn(i).GetName() fieldTypeCode = layerDefinition.GetFieldDefn(i).GetType() fieldType = layerDefinition.GetFieldDefn(i).GetFieldTypeName(fieldTypeCode) fieldWidth = layerDefinition.GetFieldDefn(i).GetWidth() GetPrecision = layerDefinition.GetFieldDefn(i).GetPrecision() print fieldName + " - " + fieldType+ " " + str(fieldWidth) + " " + str(GetPrecision)
Get PostGIS Layer Fields – Get the user defined fields
This code example returns the field names of the user defined (created) fields.
from osgeo import ogr import sys databaseServer = "<IP of database server OR Name of database server" databaseName = "<Name of database>" databaseUser = "<User name>" databasePW = "<User password>" connString = "PG: host=%s dbname=%s user=%s password=%s" %(databaseServer,databaseName,databaseUser,databasePW) def GetPGLayerFields( lyr_name ): conn = ogr.Open(connString) lyr = conn.GetLayer( lyr_name ) if lyr is None: print >> sys.stderr, '[ ERROR ]: layer name = "%s" could not be found in database "%s"' % ( lyr_name, databaseName ) sys.exit( 1 ) lyrDefn = lyr.GetLayerDefn() for i in range( lyrDefn.GetFieldCount() ): print lyrDefn.GetFieldDefn( i ).GetName() # Close connection conn = None if __name__ == '__main__': if len( sys.argv ) < 2: print >> sys.stderr, '[ ERROR ]: you must pass at least one argument -- the layer name argument' sys.exit( 1 ) lyr_name = sys.argv[1] GetPGLayerFields( lyr_name )
Get PostGIS Layer Fields and Types – Get the user defined fields
This code example returns the field names of the user defined (created) fields and the data types they are.
from osgeo import ogr import sys databaseServer = "<IP of database server OR Name of database server" databaseName = "<Name of database>" databaseUser = "<User name>" databasePW = "<User password>" connString = "PG: host=%s dbname=%s user=%s password=%s" %(databaseServer,databaseName,databaseUser,databasePW) def GetPGLayerFieldTypes( lyr_name ): conn = ogr.Open(connString) lyr = conn.GetLayer( lyr_name ) if lyr is None: print >> sys.stderr, '[ ERROR ]: layer name = "%s" could not be found in database "%s"' % ( lyr_name, databaseName ) sys.exit( 1 ) lyrDefn = lyr.GetLayerDefn() for i in range( lyrDefn.GetFieldCount() ): fieldName = lyrDefn.GetFieldDefn(i).GetName() fieldTypeCode = lyrDefn.GetFieldDefn(i).GetType() fieldType = lyrDefn.GetFieldDefn(i).GetFieldTypeName(fieldTypeCode) fieldWidth = lyrDefn.GetFieldDefn(i).GetWidth() GetPrecision = lyrDefn.GetFieldDefn(i).GetPrecision() print fieldName + " - " + fieldType+ " " + str(fieldWidth) + " " + str(GetPrecision) # Close connection conn = None if __name__ == '__main__': if len( sys.argv ) < 2: print >> sys.stderr, '[ ERROR ]: you must pass at least one argument -- the layer name argument' sys.exit( 1 ) lyr_name = sys.argv[1] GetPGLayerFieldTypes( lyr_name )
Get a Layer’s Capabilities
from osgeo import ogr ds = ogr.Open("states.shp",0) layer = ds.GetLayer() capabilities = [ ogr.OLCRandomRead, ogr.OLCSequentialWrite, ogr.OLCRandomWrite, ogr.OLCFastSpatialFilter, ogr.OLCFastFeatureCount, ogr.OLCFastGetExtent, ogr.OLCCreateField, ogr.OLCDeleteField, ogr.OLCReorderFields, ogr.OLCAlterFieldDefn, ogr.OLCTransactions, ogr.OLCDeleteFeature, ogr.OLCFastSetNextByIndex, ogr.OLCStringsAsUTF8, ogr.OLCIgnoreFields ] print("Layer Capabilities:") for cap in capabilities: print(" %s = %s" % (cap, layer.TestCapability(cap)))
Get WFS layers and iterate over features
This recipe queries a WFS services and fetches features from a large layer. It sets up the GDAL configuration to using WFS paging if it is supported.
import sys try: from osgeo import ogr, osr, gdal except: sys.exit('ERROR: cannot find GDAL/OGR modules') # Set the driver (optional) wfs_drv = ogr.GetDriverByName('WFS') # Speeds up querying WFS capabilities for services with alot of layers gdal.SetConfigOption('OGR_WFS_LOAD_MULTIPLE_LAYER_DEFN', 'NO') # Set config for paging. Works on WFS 2.0 services and WFS 1.0 and 1.1 with some other services. gdal.SetConfigOption('OGR_WFS_PAGING_ALLOWED', 'YES') gdal.SetConfigOption('OGR_WFS_PAGE_SIZE', '10000') # Open the webservice url = 'http://example-service.com/wfs' wfs_ds = wfs_drv.Open('WFS:' + url) if not wfs_ds: sys.exit('ERROR: can not open WFS datasource') else: pass # iterate over available layers for i in range(wfs_ds.GetLayerCount()): layer = wfs_ds.GetLayerByIndex(i) srs = layer.GetSpatialRef() print 'Layer: %s, Features: %s, SR: %s...' % (layer.GetName(), layer.GetFeatureCount(), srs.ExportToWkt()[0:50]) # iterate over features feat = layer.GetNextFeature() while feat is not None: feat = layer.GetNextFeature() # do something more.. feat = None # Get a specific layer layer = wfs_ds.GetLayerByName("largelayer") if not layer: sys.exit('ERROR: can not find layer in service') else: pass
Set HTTP Proxy options before fetching a web datasource
This recipe sets options for a HTTP proxy service that using NTLM authentication (typical for corporate environments that using Active directory for single sign-on proxy support). More information about the GDAL HTTP proxy options can be found here
import sys try: from osgeo import ogr, osr, gdal except: sys.exit('ERROR: cannot find GDAL/OGR modules') server = 'proxy.example.com' port = 3128 # specify proxy server gdal.SetConfigOption('GDAL_HTTP_PROXY', server + ':' + port) # setup proxy authentication option for NTLM with no username or password so single sign-on works gdal.SetConfigOption('GDAL_PROXY_AUTH', 'NTLM') gdal.SetConfigOption('GDAL_HTTP_PROXYUSERPWD', ' : ') # now fetch a HTTP datasource and do something... ds = ogr.Open('http://featureserver/cities/.geojson') if not ds: sys.exit('ERROR: can not open GeoJSON datasource') lyr = ds.GetLayer('OGRGeoJSON') for feat in lyr: geom = feat.GetGeometryRef() print geom.ExportToWkt()
Read a CSV of Coordinates as an OGRVRTLayer
GDAL/OGR has a Virtual Format spec that allows you to derive layers from flat tables such as a CSV – it does a lot more than that too so go read about it. In the example below we are reading in a CSV with X,Y columns and values. That CSV file is wrapped by an XML file that describes it as an OGR layer. Below are all the necessary pieces and a script that reads the XML file and prints out point geometries.
Our CSV file named example.csv looks like this:
ID,X,Y 1,-127.234343,47.234325 2,-127.003243,46.234343 3,-127.345646,45.234324 4,-126.234324,44.324234
Our OGRVRTLayer XML file called example_wrapper.vrt looks like this:
<OGRVRTDataSource> <OGRVRTLayer name="example"> <SrcDataSource>example.csv</SrcDataSource> <SrcLayer>example</SrcLayer> <GeometryType>wkbPoint</GeometryType> <LayerSRS>WGS84</LayerSRS> <GeometryField encoding="PointFromColumns" x="X" y="Y"/> </OGRVRTLayer> </OGRVRTDataSource>
Now let’s print out the point geometries:
from osgeo import ogr ogr.UseExceptions() inDataSource = ogr.Open("example_wrapper.vrt") lyr = inDataSource.GetLayer('example') for feat in lyr: geom = feat.GetGeometryRef() print geom.ExportToWkt()
Create a new Layer from the extent of an existing Layer
from osgeo import ogr import os # Get a Layer's Extent inShapefile = "states.shp" inDriver = ogr.GetDriverByName("ESRI Shapefile") inDataSource = inDriver.Open(inShapefile, 0) inLayer = inDataSource.GetLayer() extent = inLayer.GetExtent() # Create a Polygon from the extent tuple ring = ogr.Geometry(ogr.wkbLinearRing) ring.AddPoint(extent[0],extent[2]) ring.AddPoint(extent[1], extent[2]) ring.AddPoint(extent[1], extent[3]) ring.AddPoint(extent[0], extent[3]) ring.AddPoint(extent[0],extent[2]) poly = ogr.Geometry(ogr.wkbPolygon) poly.AddGeometry(ring) # Save extent to a new Shapefile outShapefile = "states_extent.shp" outDriver = ogr.GetDriverByName("ESRI Shapefile") # Remove output shapefile if it already exists if os.path.exists(outShapefile): outDriver.DeleteDataSource(outShapefile) # Create the output shapefile outDataSource = outDriver.CreateDataSource(outShapefile) outLayer = outDataSource.CreateLayer("states_extent", geom_type=ogr.wkbPolygon) # Add an ID field idField = ogr.FieldDefn("id", ogr.OFTInteger) outLayer.CreateField(idField) # Create the feature and set values featureDefn = outLayer.GetLayerDefn() feature = ogr.Feature(featureDefn) feature.SetGeometry(poly) feature.SetField("id", 1) outLayer.CreateFeature(feature) feature = None # Save and close DataSource inDataSource = None outDataSource = None
Save the convex hull of all geometry from an input Layer to an output Layer
from osgeo import ogr import os # Get a Layer inShapefile = "states.shp" inDriver = ogr.GetDriverByName("ESRI Shapefile") inDataSource = inDriver.Open(inShapefile, 0) inLayer = inDataSource.GetLayer() # Collect all Geometry geomcol = ogr.Geometry(ogr.wkbGeometryCollection) for feature in inLayer: geomcol.AddGeometry(feature.GetGeometryRef()) # Calculate convex hull convexhull = geomcol.ConvexHull() # Save extent to a new Shapefile outShapefile = "states_convexhull.shp" outDriver = ogr.GetDriverByName("ESRI Shapefile") # Remove output shapefile if it already exists if os.path.exists(outShapefile): outDriver.DeleteDataSource(outShapefile) # Create the output shapefile outDataSource = outDriver.CreateDataSource(outShapefile) outLayer = outDataSource.CreateLayer("states_convexhull", geom_type=ogr.wkbPolygon) # Add an ID field idField = ogr.FieldDefn("id", ogr.OFTInteger) outLayer.CreateField(idField) # Create the feature and set values featureDefn = outLayer.GetLayerDefn() feature = ogr.Feature(featureDefn) feature.SetGeometry(convexhull) feature.SetField("id", 1) outLayer.CreateFeature(feature) feature = None # Save and close DataSource inDataSource = None outDataSource = None
Save centroids of input Layer to an output Layer
Inspired by: http://www.kralidis.ca/blog/2010/04/28/batch-centroid-calculations-with-python-and-ogr/
from osgeo import ogr import os # Get the input Layer inShapefile = "states.shp" inDriver = ogr.GetDriverByName("ESRI Shapefile") inDataSource = inDriver.Open(inShapefile, 0) inLayer = inDataSource.GetLayer() # Create the output Layer outShapefile = "states_centroids.shp" outDriver = ogr.GetDriverByName("ESRI Shapefile") # Remove output shapefile if it already exists if os.path.exists(outShapefile): outDriver.DeleteDataSource(outShapefile) # Create the output shapefile outDataSource = outDriver.CreateDataSource(outShapefile) outLayer = outDataSource.CreateLayer("states_centroids", geom_type=ogr.wkbPoint) # Add input Layer Fields to the output Layer inLayerDefn = inLayer.GetLayerDefn() for i in range(0, inLayerDefn.GetFieldCount()): fieldDefn = inLayerDefn.GetFieldDefn(i) outLayer.CreateField(fieldDefn) # Get the output Layer's Feature Definition outLayerDefn = outLayer.GetLayerDefn() # Add features to the ouput Layer for i in range(0, inLayer.GetFeatureCount()): # Get the input Feature inFeature = inLayer.GetFeature(i) # Create output Feature outFeature = ogr.Feature(outLayerDefn) # Add field values from input Layer for i in range(0, outLayerDefn.GetFieldCount()): outFeature.SetField(outLayerDefn.GetFieldDefn(i).GetNameRef(), inFeature.GetField(i)) # Set geometry as centroid geom = inFeature.GetGeometryRef() inFeature = None centroid = geom.Centroid() outFeature.SetGeometry(centroid) # Add new feature to output Layer outLayer.CreateFeature(outFeature) outFeature = None # Save and close DataSources inDataSource = None outDataSource = None
Create a New Shapefile and Add Data
This recipe parses a delimited text file of volcano location data and creates a shapefile. The CSV file volcano_data.txt
contains the following fields, separated by a tab character (\t):
- Name
- Region
- Latitude
- Longitude
- Elevation
Taken from The Geospatial Desktop book.
# Parse a delimited text file of volcano data and create a shapefile import osgeo.ogr as ogr import osgeo.osr as osr # use a dictionary reader so we can access by field name reader = csv.DictReader(open("volcano_data.txt","rb"), delimiter='\t', quoting=csv.QUOTE_NONE) # set up the shapefile driver driver = ogr.GetDriverByName("ESRI Shapefile") # create the data source data_source = driver.CreateDataSource("volcanoes.shp") # create the spatial reference, WGS84 srs = osr.SpatialReference() srs.ImportFromEPSG(4326) # create the layer layer = data_source.CreateLayer("volcanoes", srs, ogr.wkbPoint) # Add the fields we're interested in field_name = ogr.FieldDefn("Name", ogr.OFTString) field_name.SetWidth(24) layer.CreateField(field_name) field_region = ogr.FieldDefn("Region", ogr.OFTString) field_region.SetWidth(24) layer.CreateField(field_region) layer.CreateField(ogr.FieldDefn("Latitude", ogr.OFTReal)) layer.CreateField(ogr.FieldDefn("Longitude", ogr.OFTReal)) layer.CreateField(ogr.FieldDefn("Elevation", ogr.OFTInteger)) # Process the text file and add the attributes and features to the shapefile for row in reader: # create the feature feature = ogr.Feature(layer.GetLayerDefn()) # Set the attributes using the values from the delimited text file feature.SetField("Name", row['Name']) feature.SetField("Region", row['Region']) feature.SetField("Latitude", row['Latitude']) feature.SetField("Longitude", row['Longitude']) feature.SetField("Elevation", row['Elev']) # create the WKT for the feature using Python string formatting wkt = "POINT(%f %f)" % (float(row['Longitude']) , float(row['Latitude'])) # Create the point from the Well Known Txt point = ogr.CreateGeometryFromWkt(wkt) # Set the feature geometry using the point feature.SetGeometry(point) # Create the feature in the layer (shapefile) layer.CreateFeature(feature) # Dereference the feature feature = None # Save and close the data source data_source = None
Create a PostGIS table from WKT
This recipe creates a new table in an existing PostGIS database.
import ogr, osr database = 'test' usr = 'postgres' pw = '' table = 'test' wkt = "POINT (1120351.5712494177 741921.4223245403)" point = ogr.CreateGeometryFromWkt(wkt) connectionString = "PG:dbname='%s' user='%s' password='%s'" % (database,usr,pw) ogrds = ogr.Open(connectionString) srs = osr.SpatialReference() srs.ImportFromEPSG(4326) layer = ogrds.CreateLayer(table, srs, ogr.wkbPoint, ['OVERWRITE=YES'] ) layerDefn = layer.GetLayerDefn() feature = ogr.Feature(layerDefn) feature.SetGeometry(point) layer.StartTransaction() layer.CreateFeature(feature) feature = None layer.CommitTransaction()
Filter and Select Input Shapefile to New Output Shapefile Like ogr2ogr CLI
The ogr2ogr command line tool is an easy way to filter, reproject and trim columns in a shapefile. The workflow below shows how we can approximate the following ogr2ogr command with the OGR api using a decently large parcel shapefile from King County GIS .
# # this command says read in "parcel_address.shp" and write out to "junkmob.shp" # where "MINOR" column = 'HYDR' value and only output the "PIN" column # $ ogr2ogr -f "ESRI Shapefile" junkmob.shp -select pin -where "minor = 'HYDR'" parcel_address.shp
from osgeo import ogr import os, sys def main( field_name_target ): # Get the input Layer inShapefile = "~/DATA/SHAPES/KC_ADMIN/parcel_address/parcel_address.shp" inDriver = ogr.GetDriverByName("ESRI Shapefile") inDataSource = inDriver.Open(inShapefile, 0) inLayer = inDataSource.GetLayer() inLayer.SetAttributeFilter("minor = 'HYDR'") # Create the output LayerS outShapefile = os.path.join( os.path.split( inShapefile )[0], "ogr_api_filter.shp" ) outDriver = ogr.GetDriverByName("ESRI Shapefile") # Remove output shapefile if it already exists if os.path.exists(outShapefile): outDriver.DeleteDataSource(outShapefile) # Create the output shapefile outDataSource = outDriver.CreateDataSource(outShapefile) out_lyr_name = os.path.splitext( os.path.split( outShapefile )[1] )[0] outLayer = outDataSource.CreateLayer( out_lyr_name, geom_type=ogr.wkbMultiPolygon ) # Add input Layer Fields to the output Layer if it is the one we want inLayerDefn = inLayer.GetLayerDefn() for i in range(0, inLayerDefn.GetFieldCount()): fieldDefn = inLayerDefn.GetFieldDefn(i) fieldName = fieldDefn.GetName() if fieldName not in field_name_target: continue outLayer.CreateField(fieldDefn) # Get the output Layer's Feature Definition outLayerDefn = outLayer.GetLayerDefn() # Add features to the ouput Layer for inFeature in inLayer: # Create output Feature outFeature = ogr.Feature(outLayerDefn) # Add field values from input Layer for i in range(0, outLayerDefn.GetFieldCount()): fieldDefn = outLayerDefn.GetFieldDefn(i) fieldName = fieldDefn.GetName() if fieldName not in field_name_target: continue outFeature.SetField(outLayerDefn.GetFieldDefn(i).GetNameRef(), inFeature.GetField(i)) # Set geometry as centroid geom = inFeature.GetGeometryRef() outFeature.SetGeometry(geom.Clone()) # Add new feature to output Layer outLayer.CreateFeature(outFeature) outFeature = None # Save and close DataSources inDataSource = None outDataSource = None if __name__ == '__main__': if len( sys.argv ) < 2: print "[ ERROR ]: you need to pass at least one arg -- the field_names to include in output" sys.exit(1) main( sys.argv[1:] )
Merge OGR Layers
This recipe merges OGR Layers within a directory. Files can be specfied based on with what they start and end.
import os, ogr, osr outputMergefn = 'merge.shp' directory = "/Users/UserName/Downloads/" fileStartsWith = 'test' fileEndsWith = '.shp' driverName = 'ESRI Shapefile' geometryType = ogr.wkbPolygon out_driver = ogr.GetDriverByName( driverName ) if os.path.exists(outputMergefn): out_driver.DeleteDataSource(outputMergefn) out_ds = out_driver.CreateDataSource(outputMergefn) out_layer = out_ds.CreateLayer(outputMergefn, geom_type=geometryType) fileList = os.listdir(directory) for file in fileList: if file.startswith(fileStartsWith) and file.endswith(fileEndsWith): print file ds = ogr.Open(directory+file) lyr = ds.GetLayer() for feat in lyr: out_feat = ogr.Feature(out_layer.GetLayerDefn()) out_feat.SetGeometry(feat.GetGeometryRef().Clone()) out_layer.CreateFeature(out_feat) out_feat = None out_layer.SyncToDisk()
Get a list of the street names in a OSM file
This recipe takes in an OSM file and prints a list of all the names of the streets in the file.
import ogr ds = ogr.Open('map.osm') layer = ds.GetLayer(1) # layer 1 for ways nameList = [] for feature in layer: if feature.GetField("highway") != None: # only streets name = feature.GetField("name") if name != None and name not in nameList: # only streets that have a name and are not yet in the list nameList.append(name) print nameList
Create fishnet grid
This recipe creates a fishnet grid.
python grid.py grid.shp 992325.66 1484723.41 494849.32 781786.14 10000 10000
import os, sys import ogr from math import ceil def main(outputGridfn,xmin,xmax,ymin,ymax,gridHeight,gridWidth): # convert sys.argv to float xmin = float(xmin) xmax = float(xmax) ymin = float(ymin) ymax = float(ymax) gridWidth = float(gridWidth) gridHeight = float(gridHeight) # get rows rows = ceil((ymax-ymin)/gridHeight) # get columns cols = ceil((xmax-xmin)/gridWidth) # start grid cell envelope ringXleftOrigin = xmin ringXrightOrigin = xmin + gridWidth ringYtopOrigin = ymax ringYbottomOrigin = ymax-gridHeight # create output file outDriver = ogr.GetDriverByName('ESRI Shapefile') if os.path.exists(outputGridfn): os.remove(outputGridfn) outDataSource = outDriver.CreateDataSource(outputGridfn) outLayer = outDataSource.CreateLayer(outputGridfn,geom_type=ogr.wkbPolygon ) featureDefn = outLayer.GetLayerDefn() # create grid cells countcols = 0 while countcols < cols: countcols += 1 # reset envelope for rows ringYtop = ringYtopOrigin ringYbottom =ringYbottomOrigin countrows = 0 while countrows < rows: countrows += 1 ring = ogr.Geometry(ogr.wkbLinearRing) ring.AddPoint(ringXleftOrigin, ringYtop) ring.AddPoint(ringXrightOrigin, ringYtop) ring.AddPoint(ringXrightOrigin, ringYbottom) ring.AddPoint(ringXleftOrigin, ringYbottom) ring.AddPoint(ringXleftOrigin, ringYtop) poly = ogr.Geometry(ogr.wkbPolygon) poly.AddGeometry(ring) # add new geom to layer outFeature = ogr.Feature(featureDefn) outFeature.SetGeometry(poly) outLayer.CreateFeature(outFeature) outFeature = None # new envelope for next poly ringYtop = ringYtop - gridHeight ringYbottom = ringYbottom - gridHeight # new envelope for next poly ringXleftOrigin = ringXleftOrigin + gridWidth ringXrightOrigin = ringXrightOrigin + gridWidth # Save and close DataSources outDataSource = None if __name__ == "__main__": # # example run : $ python grid.py <full-path><output-shapefile-name>.shp xmin xmax ymin ymax gridHeight gridWidth # if len( sys.argv ) != 8: print "[ ERROR ] you must supply seven arguments: output-shapefile-name.shp xmin xmax ymin ymax gridHeight gridWidth" sys.exit( 1 ) main( sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4], sys.argv[5], sys.argv[6], sys.argv[7] )
Convert polygon shapefile to line shapefile
This recipe converts a poylgon shapefile to a line shapefile
import ogr, os def poly2line(input_poly,output_line): source_ds = ogr.Open(input_poly) source_layer = source_ds.GetLayer() # polygon2geometryCollection geomcol = ogr.Geometry(ogr.wkbGeometryCollection) for feat in source_layer: geom = feat.GetGeometryRef() ring = geom.GetGeometryRef(0) geomcol.AddGeometry(ring) # geometryCollection2shp shpDriver = ogr.GetDriverByName("ESRI Shapefile") if os.path.exists(output_line): shpDriver.DeleteDataSource(output_line) outDataSource = shpDriver.CreateDataSource(output_line) outLayer = outDataSource.CreateLayer(output_line, geom_type=ogr.wkbMultiLineString) featureDefn = outLayer.GetLayerDefn() outFeature = ogr.Feature(featureDefn) outFeature.SetGeometry(geomcol) outLayer.CreateFeature(outFeature) outFeature = None def main(input_poly,output_line): poly2line(input_poly,output_line) if __name__ == "__main__": input_poly = 'test_polygon.shp' output_line = 'test_line.shp' main(input_poly,output_line)
Create point shapefile with attribute data
This recipe creates a new shapefiles, adds a point to it, and adds a attribute column with a value to it.
import ogr, os # Input data pointCoord = -124.4577,48.0135 fieldName = 'test' fieldType = ogr.OFTString fieldValue = 'test' outSHPfn = 'test.shp' # Create the output shapefile shpDriver = ogr.GetDriverByName("ESRI Shapefile") if os.path.exists(outSHPfn): shpDriver.DeleteDataSource(outSHPfn) outDataSource = shpDriver.CreateDataSource(outSHPfn) outLayer = outDataSource.CreateLayer(outSHPfn, geom_type=ogr.wkbPoint ) #create point geometry point = ogr.Geometry(ogr.wkbPoint) point.AddPoint(pointCoord[0],pointCoord[1]) # create a field idField = ogr.FieldDefn(fieldName, fieldType) outLayer.CreateField(idField) # Create the feature and set values featureDefn = outLayer.GetLayerDefn() outFeature = ogr.Feature(featureDefn) outFeature.SetGeometry(point) outFeature.SetField(fieldName, fieldValue) outLayer.CreateFeature(outFeature) outFeature = None
Create buffer
This recipe buffers features of a layer and saves them to a new Layer
import ogr, os def createBuffer(inputfn, outputBufferfn, bufferDist): inputds = ogr.Open(inputfn) inputlyr = inputds.GetLayer() shpdriver = ogr.GetDriverByName('ESRI Shapefile') if os.path.exists(outputBufferfn): shpdriver.DeleteDataSource(outputBufferfn) outputBufferds = shpdriver.CreateDataSource(outputBufferfn) bufferlyr = outputBufferds.CreateLayer(outputBufferfn, geom_type=ogr.wkbPolygon) featureDefn = bufferlyr.GetLayerDefn() for feature in inputlyr: ingeom = feature.GetGeometryRef() geomBuffer = ingeom.Buffer(bufferDist) outFeature = ogr.Feature(featureDefn) outFeature.SetGeometry(geomBuffer) bufferlyr.CreateFeature(outFeature) outFeature = None def main(inputfn, outputBufferfn, bufferDist): createBuffer(inputfn, outputBufferfn, bufferDist) if __name__ == "__main__": inputfn = 'test.shp' outputBufferfn = 'testBuffer.shp' bufferDist = 10.0 main(inputfn, outputBufferfn, bufferDist)
Convert vector layer to array
This recipe converts a vector layer to an array.
[[0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] [0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] [0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0] [0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0] [0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0] [0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0] [0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1] [0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1] [0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1] [0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1] [0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0] [0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0] [0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0] [0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0] [0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0] [0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0] [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0] [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0] [0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0] [0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0] [0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0] [0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0]]
import ogr, gdal vector_fn = 'test.shp' # Define pixel_size and NoData value of new raster pixel_size = 25 NoData_value = 255 # Open the data source and read in the extent source_ds = ogr.Open(vector_fn) source_layer = source_ds.GetLayer() source_srs = source_layer.GetSpatialRef() x_min, x_max, y_min, y_max = source_layer.GetExtent() # Create the destination data source x_res = int((x_max - x_min) / pixel_size) y_res = int((y_max - y_min) / pixel_size) target_ds = gdal.GetDriverByName('MEM').Create('', x_res, y_res, gdal.GDT_Byte) target_ds.SetGeoTransform((x_min, pixel_size, 0, y_max, 0, -pixel_size)) band = target_ds.GetRasterBand(1) band.SetNoDataValue(NoData_value) # Rasterize gdal.RasterizeLayer(target_ds, [1], source_layer, burn_values=[1]) # Read as array array = band.ReadAsArray() print array
Convert polygon to points
This recipe converts a polygon to points.
import ogr, gdal import numpy as np import os polygon_fn = 'test_polygon.shp' # Define pixel_size which equals distance betweens points pixel_size = 10 # Open the data source and read in the extent source_ds = ogr.Open(polygon_fn) source_layer = source_ds.GetLayer() x_min, x_max, y_min, y_max = source_layer.GetExtent() # Create the destination data source x_res = int((x_max - x_min) / pixel_size) y_res = int((y_max - y_min) / pixel_size) target_ds = gdal.GetDriverByName('GTiff').Create('temp.tif', x_res, y_res, gdal.GDT_Byte) target_ds.SetGeoTransform((x_min, pixel_size, 0, y_max, 0, -pixel_size)) band = target_ds.GetRasterBand(1) band.SetNoDataValue(255) # Rasterize gdal.RasterizeLayer(target_ds, [1], source_layer, burn_values=[1]) # Read as array array = band.ReadAsArray() raster = gdal.Open('temp.tif') geotransform = raster.GetGeoTransform() # Convert array to point coordinates count = 0 roadList = np.where(array == 1) multipoint = ogr.Geometry(ogr.wkbMultiPoint) for indexY in roadList[0]: indexX = roadList[1][count] geotransform = raster.GetGeoTransform() originX = geotransform[0] originY = geotransform[3] pixelWidth = geotransform[1] pixelHeight = geotransform[5] Xcoord = originX+pixelWidth*indexX Ycoord = originY+pixelHeight*indexY point = ogr.Geometry(ogr.wkbPoint) point.AddPoint(Xcoord, Ycoord) multipoint.AddGeometry(point) count += 1 # Write point coordinates to Shapefile shpDriver = ogr.GetDriverByName("ESRI Shapefile") if os.path.exists('points.shp'): shpDriver.DeleteDataSource('points.shp') outDataSource = shpDriver.CreateDataSource('points.shp') outLayer = outDataSource.CreateLayer('points.shp', geom_type=ogr.wkbMultiPoint) featureDefn = outLayer.GetLayerDefn() outFeature = ogr.Feature(featureDefn) outFeature.SetGeometry(multipoint) outLayer.CreateFeature(outFeature) outFeature = None # Remove temporary files os.remove('temp.tif')
转载自:https://blog.csdn.net/dou3516/article/details/82912782