溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

python中如何使用gdal對shp讀取、新建和更新

發(fā)布時間:2021-03-26 11:09:52 來源:億速云 閱讀:1361 作者:小新 欄目:開發(fā)技術(shù)

這篇文章主要介紹了python中如何使用gdal對shp讀取、新建和更新,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

1.讀取shp文件

#-*- coding: cp936 -*-
try:
   from osgeo import gdal
   from osgeo import ogr
exceptImportError:
   import gdal
   import ogr
 
defReadVectorFile():
   # 為了支持中文路徑,請?zhí)砑酉旅孢@句代碼
   gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8","NO")
   # 為了使屬性表字段支持中文,請?zhí)砑酉旅孢@句
   gdal.SetConfigOption("SHAPE_ENCODING","")
 
   strVectorFile ="E:\\Datum\\GDALCsTest\\Debug\\beijing.shp"
 
   # 注冊所有的驅(qū)動
   ogr.RegisterAll()
 
   #打開數(shù)據(jù)
   ds = ogr.Open(strVectorFile, 0)
   if ds == None:
     print("打開文件【%s】失敗!", strVectorFile)
     return
 
   print("打開文件【%s】成功!", strVectorFile)
 
   # 獲取該數(shù)據(jù)源中的圖層個數(shù),一般shp數(shù)據(jù)圖層只有一個,如果是mdb、dxf等圖層就會有多個
   iLayerCount = ds.GetLayerCount()
 
   # 獲取第一個圖層
   oLayer = ds.GetLayerByIndex(0)
   if oLayer == None:
     print("獲取第%d個圖層失??!\n", 0)
     return
 
   # 對圖層進行初始化,如果對圖層進行了過濾操作,執(zhí)行這句后,之前的過濾全部清空
   oLayer.ResetReading()
 
   # 通過屬性表的SQL語句對圖層中的要素進行篩選,這部分詳細參考SQL查詢章節(jié)內(nèi)容
   oLayer.SetAttributeFilter("\"NAME99\"LIKE \"北京市市轄區(qū)\"")
 
   # 通過指定的幾何對象對圖層中的要素進行篩選
   #oLayer.SetSpatialFilter()
 
   # 通過指定的四至范圍對圖層中的要素進行篩選
   #oLayer.SetSpatialFilterRect()
 
   # 獲取圖層中的屬性表表頭并輸出
   print("屬性表結(jié)構(gòu)信息:")
   oDefn = oLayer.GetLayerDefn()
   iFieldCount = oDefn.GetFieldCount()
   for iAttr in range(iFieldCount):
     oField =oDefn.GetFieldDefn(iAttr)
     print( "%s: %s(%d.%d)" % ( \
          oField.GetNameRef(),\
          oField.GetFieldTypeName(oField.GetType() ), \
          oField.GetWidth(),\
          oField.GetPrecision()))
 
   # 輸出圖層中的要素個數(shù)
   print("要素個數(shù) = %d", oLayer.GetFeatureCount(0))
 
   oFeature = oLayer.GetNextFeature()
   # 下面開始遍歷圖層中的要素
   while oFeature is not None:
     print("當前處理第%d個: \n屬性值:", oFeature.GetFID())
     # 獲取要素中的屬性表內(nèi)容
     for iField inrange(iFieldCount):
       oFieldDefn =oDefn.GetFieldDefn(iField)
       line = " %s (%s) = " % ( \
            oFieldDefn.GetNameRef(),\
            ogr.GetFieldTypeName(oFieldDefn.GetType()))
 
       ifoFeature.IsFieldSet( iField ):
          line = line+ "%s" % (oFeature.GetFieldAsString( iField ) )
       else:
          line = line+ "(null)"
 
       print(line)
  
     # 獲取要素中的幾何體
     oGeometry =oFeature.GetGeometryRef()
 
     # 為了演示,只輸出一個要素信息
     break
 
   print("數(shù)據(jù)集關(guān)閉!")

2.新建shp文件

#-*- coding: cp936 -*-
try:
   from osgeo import gdal
   from osgeo import ogr
exceptImportError:
   import gdal
   import ogr
 
defWriteVectorFile():
   # 為了支持中文路徑,請?zhí)砑酉旅孢@句代碼
   gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8","NO")
   # 為了使屬性表字段支持中文,請?zhí)砑酉旅孢@句
   gdal.SetConfigOption("SHAPE_ENCODING","")
 
   strVectorFile ="E:\\TestPolygon.shp"
 
   # 注冊所有的驅(qū)動
   ogr.RegisterAll()
 
   # 創(chuàng)建數(shù)據(jù),這里以創(chuàng)建ESRI的shp文件為例
   strDriverName = "ESRIShapefile"
   oDriver =ogr.GetDriverByName(strDriverName)
   if oDriver == None:
     print("%s 驅(qū)動不可用!\n", strDriverName)
     return
  
   # 創(chuàng)建數(shù)據(jù)源
   oDS =oDriver.CreateDataSource(strVectorFile)
   if oDS == None:
     print("創(chuàng)建文件【%s】失??!", strVectorFile)
     return
 
   # 創(chuàng)建圖層,創(chuàng)建一個多邊形圖層,這里沒有指定空間參考,如果需要的話,需要在這里進行指定
   papszLCO = []
   oLayer =oDS.CreateLayer("TestPolygon", None, ogr.wkbPolygon, papszLCO)
   if oLayer == None:
     print("圖層創(chuàng)建失??!\n")
     return
 
   # 下面創(chuàng)建屬性表
   # 先創(chuàng)建一個叫FieldID的整型屬性
   oFieldID =ogr.FieldDefn("FieldID", ogr.OFTInteger)
   oLayer.CreateField(oFieldID, 1)
 
   # 再創(chuàng)建一個叫FeatureName的字符型屬性,字符長度為50
   oFieldName =ogr.FieldDefn("FieldName", ogr.OFTString)
   oFieldName.SetWidth(100)
   oLayer.CreateField(oFieldName, 1)
 
   oDefn = oLayer.GetLayerDefn()
 
   # 創(chuàng)建三角形要素
   oFeatureTriangle = ogr.Feature(oDefn)
   oFeatureTriangle.SetField(0, 0)
   oFeatureTriangle.SetField(1, "三角形")
   geomTriangle =ogr.CreateGeometryFromWkt("POLYGON ((0 0,20 0,10 15,0 0))")
   oFeatureTriangle.SetGeometry(geomTriangle)
   oLayer.CreateFeature(oFeatureTriangle)
 
   # 創(chuàng)建矩形要素
   oFeatureRectangle = ogr.Feature(oDefn)
   oFeatureRectangle.SetField(0, 1)
   oFeatureRectangle.SetField(1, "矩形")
   geomRectangle =ogr.CreateGeometryFromWkt("POLYGON ((30 0,60 0,60 30,30 30,30 0))")
   oFeatureRectangle.SetGeometry(geomRectangle)
   oLayer.CreateFeature(oFeatureRectangle)
 
   # 創(chuàng)建五角形要素
   oFeaturePentagon = ogr.Feature(oDefn)
   oFeaturePentagon.SetField(0, 2)
   oFeaturePentagon.SetField(1, "五角形")
   geomPentagon =ogr.CreateGeometryFromWkt("POLYGON ((70 0,85 0,90 15,80 30,65 15,700))")
   oFeaturePentagon.SetGeometry(geomPentagon)
   oLayer.CreateFeature(oFeaturePentagon)
 
   oDS.Destroy()
   print("數(shù)據(jù)集創(chuàng)建完成!\n")

3.更新

其實更新無非就是獲取到field然后設(shè)置新值就可以了

其實用SetField()方法就行

import os,sys
from osgeo import gdal
from osgeo import ogr
from osgeo import osr
import numpy
import transformer
# 為了支持中文路徑,請?zhí)砑酉旅孢@句代碼
 
 
pathname = sys.argv[1]
choose = sys.argv[2]
gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "NO")
# 為了使屬性表字段支持中文,請?zhí)砑酉旅孢@句
gdal.SetConfigOption("SHAPE_ENCODING", "")
# 注冊所有的驅(qū)動
ogr.RegisterAll()
# 數(shù)據(jù)格式的驅(qū)動
driver = ogr.GetDriverByName('ESRI Shapefile')
ds = driver.Open(pathname, update=1)
if ds is None:
 print 'Could not open %s'%pathname
 sys.exit(1)
# 獲取第0個圖層
layer0 = ds.GetLayerByIndex(0);
# 投影
spatialRef = layer0.GetSpatialRef();
# 輸出圖層中的要素個數(shù)
print '要素個數(shù)=%d'%(layer0.GetFeatureCount(0))
print '屬性表結(jié)構(gòu)信息'
defn = layer0.GetLayerDefn()
fieldindex = defn.GetFieldIndex('x')
xfield = defn.GetFieldDefn(fieldindex)
#新建field
fieldDefn = ogr.FieldDefn('newx', xfield.GetType())
fieldDefn.SetWidth(32)
fieldDefn.SetPrecision(6)
layer0.CreateField(fieldDefn,1)
fieldDefn = ogr.FieldDefn('newy', xfield.GetType())
fieldDefn.SetWidth(32)
fieldDefn.SetPrecision(6)
layer0.CreateField(fieldDefn,1)
feature = layer0.GetNextFeature()
# 下面開始遍歷圖層中的要素
while feature is not None:
 # 獲取要素中的屬性表內(nèi)容
 x = feature.GetFieldAsDouble('x')
 y = feature.GetFieldAsDouble('y')
 newx, newy = transformer.begintrans(choose, x, y)
 feature.SetField('newx', newx)
 feature.SetField('newy', newy)
 layer0.SetFeature(feature)
 feature = layer0.GetNextFeature()
feature.Destroy()
ds.Destroy()

這里我其實想說最重要的是這個SetFeature(),就是你更新好了field的feature一定要重新set一下,不然是根本起不到任何改變的。新建的時候有createfeature,已經(jīng)設(shè)置了,所以不需要set。

網(wǎng)上的教程都是新建和讀取,都沒有提到這個,結(jié)果自己蠢到試了好久都沒有發(fā)現(xiàn)問題在哪,以為是什么數(shù)據(jù)類型與設(shè)置字段屬性不匹配,一頭霧水哈哈哈。

補充知識:python使用GDAL生成shp文件

GDAL是一個開源的地理工具包,其支持基本所有的地理操作,其有python、java、c等語言包,是地理信息C端開發(fā)不可越過的工具,鑒于python語言的簡單性,這里使用python中GDAL包來進行shp文件的生成,這里本質(zhì)是利用ogc地理標準的坐標字符串來生成shp。

第一步:安裝GDAL環(huán)境,建議下載后,本地安裝,注意與python版本號要對應(yīng),可參考網(wǎng)上教程。

第二部:代碼分析

引入GDAL工具包

import osgeo.ogr as ogr
import osgeo.osr as osr

注冊驅(qū)動,這里是ESRI Shapefile類型,并設(shè)置shp文件名稱

driver = ogr.GetDriverByName("ESRI Shapefile")
data_source = driver.CreateDataSource("ceshi.shp")

注入投影信息,這里使用的4326,表示經(jīng)緯度坐標,根據(jù)情況可以自行更改

srs = osr.SpatialReference()
srs.ImportFromEPSG(4326)

這里定義的是,生成的要素類型,包括點、線、面

#ogr.wkbPoint 點
#ogr.wkbLineString 線
#ogr.wkbMultiPolygon 面

這里的圖層名稱要與上面注冊驅(qū)動的shp名稱一致

layer = data_source.CreateLayer("ceshi", srs, ogr.wkbLineString)

這里設(shè)置要素的屬性字段,其中設(shè)置了兩個字段,分別是Name、data,其中ogr.OFTString表示字符串類型,其長度都是14字節(jié),可自行設(shè)置寬度

python中如何使用gdal對shp讀取、新建和更新

field_name = ogr.FieldDefn("Name", ogr.OFTString)
field_name.SetWidth(14)
layer.CreateField(field_name)
field_name = ogr.FieldDefn("data", ogr.OFTString)
field_name.SetWidth(14)
layer.CreateField(field_name)

在生成的字段名中插入要素值,即屬性表中每行的值

feature = ogr.Feature(layer.GetLayerDefn())
feature.SetField("Name", "ceshi")
feature.SetField("data", "1.2")

核心部分,生成line數(shù)據(jù)

其中各要素格式如下:

POINT(6 10)
LINESTRING(3 4,10 50,20 25)
POLYGON((1 1,5 1,5 5,1 5,1 1),(2 2,2 3,3 3,3 2,2 2))
MULTIPOINT(3.5 5.6, 4.8 10.5)
MULTILINESTRING((3 4,10 50,20 25),(-5 -8,-10 -8,-15 -4))
MULTIPOLYGON(((1 1,5 1,5 5,1 5,1 1),(2 2,2 3,3 3,3 2,2 2)),((6 3,9 2,9 4,6 3)))
GEOMETRYCOLLECTION(POINT(4 6),LINESTRING(4 6,7 10))
POINT ZM (1 1 5 60)
POINT M (1 1 80)

需要注意的是,這里應(yīng)該與上面定義的生成要素的類型保持一致,最后是清空緩存,這里多說一句,字符串語法與postgis等開源gis一致,都遵循ogc國際標準

wkt = 'LINESTRING(3 4,10 50,20 25)'
line = ogr.CreateGeometryFromWkt(wkt)
feature.SetGeometry(line)
layer.CreateFeature(feature)

feature = None
data_source = None

結(jié)果如下:

python中如何使用gdal對shp讀取、新建和更新

用arcgis打開

python中如何使用gdal對shp讀取、新建和更新

可以使用該方法,下載在線shp數(shù)據(jù),只需要知道所需要素的geojson格式數(shù)據(jù)中坐標串即可?;蛘邎D像識別中獲取的矢量邊界賦予經(jīng)緯度。

感謝你能夠認真閱讀完這篇文章,希望小編分享的“python中如何使用gdal對shp讀取、新建和更新”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,更多相關(guān)知識等著你來學(xué)習!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI