Python+GDAL/OGRベクトルデータ読み書き
一般的なベクトルデータフォーマットはShapefile、GeoJSON、CSV、およびファイルデータベースgdbと空間データベースPostGISであり、どのようなフォーマットのデータでもどのように格納しても、データソースを開き、ベクトルレイヤを取得した後(詳細はOGR操作ベクトルデータのクラス構造図を参照)、データに対する操作は同じである.ベクトルデータの読み書きについて詳しく説明します.
一、異なるベクトルファイルを開く
1、データソースを開く関数を定義し、すべてのレイヤーを巡り、名前とレイヤーを出力する
2.PostGISデータソースを開く
データソースを開いてレイヤーを出力する方法で、ローカルのPost GISデータベースpostgis_を開きます.24_sample、出力レイヤーは以下の通りです.
3、フォルダデータソース(shapefilesとCSV)を開く
shapefilesフォルダを開き、次のように出力します.
二、ベクトルデータを読み取る
ベクトルデータを読み込むには、次の手順に従います.
1、データソースを開く;
2、レイヤーを取得する;
3、レイヤーの要素を取得する;
4、フィーチャのプロパティとジオメトリ情報を取得します.
次に、ベクトルデータを読み込むコードクリップを示します.
三、データメタデータの取得
データ範囲、ジオメトリタイプ、スペースリファレンス、レイヤオブジェクトのサマリー情報など、ベクトルデータのメタデータです.次のコードクリップは、これらのメタデータ情報を取得する方法を示します.
四、ベクトルデータ書き込み
1、ベクトルデータの書き込みの構想は以下の通りである:
(1)データソースを読み書きモードで開く(作成する)
(2)追加する要素のレイヤーを取得する(または、新たにレイヤーを作成して要素を追加する).
(3)空のフィーチャを作成し、ジオメトリとアトリビュートに値を割り当てます.
(4)作成したフィーチャをレイヤーに挿入する.
次に、レイヤー内のフィーチャを使用して新しいレイヤーを作成する詳細コードを示します.
2、新しいデータソースを作成する
新しいデータソースを作成する鍵は、正しいドライバを使用することであり、各ドライバは1つのタイプのベクトルデータのみを処理します.ドライバを取得するには、(1)開いているデータセットから取得します.これにより、既存のデータソースベクトルデータフォーマットと同じ新しいデータソースを作成できます.(2)OGRのGetDriverByName関数を使用して、そのドライバの略称を渡します.ドライバの名前はOGRのウェブサイトで紹介されています.次はコードクリップです.
3、新規属性フィールド
レイヤーにフィールドを追加するには、フィールド名、データ型、フィールド、精度などの重要な情報を含むFieldDefnオブジェクトが必要です.次に、新しいプロパティフィールドのコードクリップを示します.
五、既存データの更新
ベクトルデータ処理を行う場合、新しいデータセットを作成するのではなく、既存のデータを更新する必要がある場合があります.データフォーマットに応じて、更新およびサポートできる編集操作があります.一般的な更新データ操作には、レイヤー定義(プロパティフィールド)、フィーチャ追加、更新、削除などがあります.以下、それぞれ説明する.
1、レイヤー定義を変更する
属性フィールドの定義の変更、属性フィールドの追加、および属性フィールドの削除が含まれます.具体的なコードクリップは次のとおりです.
2、要素の追加、更新、削除
データを更新した後、一般的にデータベースを圧縮、再編成または再計算する空間範囲などが必要です.以下のようにします.
一、異なるベクトルファイルを開く
1、データソースを開く関数を定義し、すべてのレイヤーを巡り、名前とレイヤーを出力する
'''
:fn
is_write ,0 ,1
'''
def print_layers(fn, is_write):
ds = ogr.Open(fn, is_write)
if ds is None:
#raise OSError('Could not open %s', fn)
raise OSError('Could not open {}'.format(fn))
for i in range(ds.GetLayerCount()):
lyr = ds.GetLayer(i)
print('{0}:{1}'.format(i, lyr.GetName()))
2.PostGISデータソースを開く
データソースを開いてレイヤーを出力する方法で、ローカルのPost GISデータベースpostgis_を開きます.24_sample、出力レイヤーは以下の通りです.
# postgis
print_layers('PG:user=postgres password=postgis dbname=postgis_24_sample', 0)
0:tiger.county
1:tiger.state
2:tiger.place
3:tiger.cousub
4:tiger.edges
5:tiger.addrfeat
6:tiger.faces
7:tiger.zcta5
8:tiger.tract
9:tiger.tabblock
10:tiger.bg
3、フォルダデータソース(shapefilesとCSV)を開く
shapefilesフォルダを開き、次のように出力します.
# shapefile
shp_fn = r'E:\HZZ_GXDP_Spatial_Data'
print_layers(shp_fn, 0)
0:CommunityRiver
1:CountyRiver
2:StreetRiver
3:Video
4:WRY
二、ベクトルデータを読み取る
ベクトルデータを読み込むには、次の手順に従います.
1、データソースを開く;
2、レイヤーを取得する;
3、レイヤーの要素を取得する;
4、フィーチャのプロパティとジオメトリ情報を取得します.
次に、ベクトルデータを読み込むコードクリップを示します.
import sys
from osgeo import ogr
import ospybook as pb
fn = r'D:\soft\geoprocessing-with-python\china_basic_map'
ds = ogr.Open(fn, 0)
if ds is None:
sys.exit('Could not open {0}.'.format(fn))
''' '''
lyr = ds.GetLayer(0)
print(lyr.GetName())
i = 0
for fea in lyr:
pt = fea.geometry()
x = pt.GetX()
y = pt.GetY()
''' '''
code = fea.GetField('GBCODE')
''' '''
length = fea.LENGTH
''' 2'''
lpoly_ = fea['LPOLY_']
''' '''
fnode_ = fea.GetField(0)
''' '''
str_len = fea.GetFieldAsString('LENGTH')
print(code, length, fnode_, lpoly_, str_len, x, y)
i += 1
if i == 20:
break
''' '''
lyr2 = ds.GetLayer(' ')
print(lyr2.GetName())
三、データメタデータの取得
データ範囲、ジオメトリタイプ、スペースリファレンス、レイヤオブジェクトのサマリー情報など、ベクトルデータのメタデータです.次のコードクリップは、これらのメタデータ情報を取得する方法を示します.
import sys
from osgeo import ogr
fn = r'D:\soft\geoprocessing-with-python\china_basic_map'
ds = ogr.Open(fn, 0)
if ds is None:
sys.exit('Could not open {0}.'.format(fn))
lyr = ds.GetLayer(0)
''' '''
extent = lyr.GetExtent()
print(extent)
'''(73.44696044921875, 135.08583068847656, 3.408477306365967, 53.557926177978516)'''
'''(min_x, max_x, min_y, max_y)'''
''' , '''
'''1: , 2: , 3: '''
geom_type = lyr.GetGeomType()
print(geom_type) #2
print(geom_type == ogr.wkbPoint) #False
print(geom_type == ogr.wkbLineString) #True
print(geom_type == ogr.wkbPolygon) #False
''' '''
fea = lyr.GetFeature(0)
print(fea.geometry().GetGeometryType()) #2
print(fea.geometry().GetGeometryName()) #LINESTRING
''' '''
print(lyr.GetSpatialRef())
# GEOGCS["GCS_WGS_1984",
# DATUM["WGS_1984",
# SPHEROID["WGS_84",6378137.0,298.257223563]],
# PRIMEM["Greenwich",0.0],
# UNIT["Degree",0.0174532925199433],
# AUTHORITY["EPSG","4326"]]
print(lyr.schema)
''' '''
for field in lyr.schema:
print(field.name, field.GetTypeName())
# FNODE_ Integer64
# TNODE_ Integer64
# LPOLY_ Integer64
# RPOLY_ Integer64
# LENGTH Real
# BOU2_4M_ Integer64
# BOU2_4M_ID Integer64
# GBCODE Integer
四、ベクトルデータ書き込み
1、ベクトルデータの書き込みの構想は以下の通りである:
(1)データソースを読み書きモードで開く(作成する)
(2)追加する要素のレイヤーを取得する(または、新たにレイヤーを作成して要素を追加する).
(3)空のフィーチャを作成し、ジオメトリとアトリビュートに値を割り当てます.
(4)作成したフィーチャをレイヤーに挿入する.
次に、レイヤー内のフィーチャを使用して新しいレイヤーを作成する詳細コードを示します.
# -*- coding:utf-8 -*-
import sys
from osgeo import ogr
''' ( )'''
fn = r'D:\soft\geoprocessing-with-python\china_basic_map'
''' '''
ds = ogr.Open(fn, 1)
if ds is None:
sys.exit('Could not open {0}.'.format(fn))
in_lyr = ds.GetLayer(' ')
# lyr = ds.GetLayer(' ')
#
# from ospybook.vectorplotter import VectorPlotter
# vp = VectorPlotter(False)
# vp.plot(lyr, fill=False)
# vp.draw()
''' , '''
if ds.GetLayer('capital_city'):
ds.DeleteLayer('capital_city')
out_lyr = ds.CreateLayer('capital_city',
in_lyr.GetSpatialRef(),
ogr.wkbPoint)
''' '''
out_lyr.CreateFields(in_lyr.schema)
''' '''
out_defn = out_lyr.GetLayerDefn()
out_fea = ogr.Feature(out_defn)
for in_fea in in_lyr:
geom = in_fea.geometry()
out_fea.SetGeometry(geom)
for i in range(in_fea.GetFieldCount()):
value = in_fea.GetField(i)
if i != 5:
out_fea.SetField(i, value)
else:
print(value)
out_lyr.CreateFeature(out_fea)
2、新しいデータソースを作成する
新しいデータソースを作成する鍵は、正しいドライバを使用することであり、各ドライバは1つのタイプのベクトルデータのみを処理します.ドライバを取得するには、(1)開いているデータセットから取得します.これにより、既存のデータソースベクトルデータフォーマットと同じ新しいデータソースを作成できます.(2)OGRのGetDriverByName関数を使用して、そのドライバの略称を渡します.ドライバの名前はOGRのウェブサイトで紹介されています.次はコードクリップです.
'''''''''' '''''''''
import sys
from osgeo import ogr
fn = r'D:\soft\geoprocessing-with-python\china_basic_map'
''' : '''
ds = ogr.Open(fn, 0)
if ds is None:
sys.exit('Could not open {0}.'.format(fn))
driver = ds.GetDriver()
print(driver.GetName())
''' :GetDriverByName'''
json_driver = ogr.GetDriverByName('GeoJSON')
print(json_driver.GetName())
''' GeoJson , '''
json_fn = r'D:\soft\geoprocessing-with-python\china_basic_map\json_fn.json'
json_ds = json_driver.CreateDataSource(json_fn)
if json_ds is None:
sys.exit('Could not create {0}'.format(json_fn))
print(json_ds)
3、新規属性フィールド
レイヤーにフィールドを追加するには、フィールド名、データ型、フィールド、精度などの重要な情報を含むFieldDefnオブジェクトが必要です.次に、新しいプロパティフィールドのコードクリップを示します.
'''UseExceptions'''
ogr.UseExceptions()
json_fn = r'D:\soft\geoprocessing-with-python\china_basic_map\json_fn4.json'
json_driver = ogr.GetDriverByName('GeoJSON')
print('start')
try:
json_ds = json_driver.CreateDataSource(json_fn)
''' '''
lyr = json_ds.CreateLayer('layer')
coord_fld = ogr.FieldDefn('X', ogr.OFTReal)
coord_fld.SetWidth(8)
coord_fld.SetPrecision(3)
lyr.CreateField(coord_fld)
coord_fld.SetName('Y')
lyr.CreateField(coord_fld)
#
fea = ogr.Feature(lyr.GetLayerDefn())
fea.SetField('X', 12.34)
fea.SetFID(1)
lyr.CreateFeature(fea)
# ( )
json_ds.SyncToDisk()
except RuntimeError as e:
print(e)
print('end')
五、既存データの更新
ベクトルデータ処理を行う場合、新しいデータセットを作成するのではなく、既存のデータを更新する必要がある場合があります.データフォーマットに応じて、更新およびサポートできる編集操作があります.一般的な更新データ操作には、レイヤー定義(プロパティフィールド)、フィーチャ追加、更新、削除などがあります.以下、それぞれ説明する.
1、レイヤー定義を変更する
属性フィールドの定義の変更、属性フィールドの追加、および属性フィールドの削除が含まれます.具体的なコードクリップは次のとおりです.
import sys
from osgeo import ogr
''''''' '''''''
fn = r'D:\soft\geoprocessing-with-python\china_basic_map'
ds = ogr.Open(fn, 1)
if ds is None:
sys.exit('Could not open {0}.'.format(fn))
''' ( 、 、 )'''
lyr = ds.GetLayer(0)
lyrdefn = lyr.GetLayerDefn()
i = lyrdefn.GetFieldIndex('GBCODE')
''' '''
fld_type = lyrdefn.GetFieldDefn(i).GetType()
print(fld_type)
''' '''
fld_defn = ogr.FieldDefn('GBCODECODE', fld_type)
fld_defn2 = ogr.FieldDefn('NEWFIELD4', ogr.OFTInteger)
''' ALTER_NAME_FLAG , '''
lyr.AlterFieldDefn(i, fld_defn, ogr.ALTER_NAME_FLAG)
''' '''
lyr.CreateField(fld_defn2)
''' ( )'''
lyr.DeleteField(lyr.FindFieldIndex('NEWFIELD', 0))
lyr.DeleteField(lyrdefn.GetFieldIndex('NEWFIELD2'))
2、要素の追加、更新、削除
''' 、 '''
fn = r'D:\soft\geoprocessing-with-python\china_basic_map'
ds = ogr.Open(fn, 1)
if ds is None:
sys.exit('Could not open {0}.'.format(fn))
# ( )
lyr = ds.GetLayer(0)
lyr.CreateField(ogr.FieldDefn('NEWFIELD', ogr.OFTInteger))
n = 1
for fea in lyr:
fea.SetField('NEWFIELD', n*n)
lyr.SetFeature(fea)
n += 1
#
for fea in lyr:
print(fea.GetField('NEWFIELD'))
if fea.GetField('NEWFIELD') == 3179089:
lyr.DeleteFeature(fea.GetFID())
print(lyr.GetFeatureCount())
データを更新した後、一般的にデータベースを圧縮、再編成または再計算する空間範囲などが必要です.以下のようにします.
ds.ExecuteSQL('REPACK ' + lyr.GetName()) #
ds.ExecuteSQL('VACUUM') #
ds.ExecuteSQL('RECOMPUTE EXTENT ON ' + lyr.GetName()) #
print(lyr.GetExtent())