GDALを使用してPythonの機能ごとにシェープファイルを分割しますか?


15

Pythonで機能ごとにシェープファイルを分割することは可能ですか?(最良の解決策は、結果のベクトルオブジェクトを一時的にディスクではなくメモリに保存できるソリューションです)。

理由:シェープファイルのいくつかの異なるサブセットでgdal rasterizeLayer関数を使用したい。この関数には、osgeo.ogr.Layerオブジェクトが必要です。


まあ、私は少し試してみましたが、次のように機能します。次のように、フィーチャごとにgdalレイヤーオブジェクトのジオメトリを取得できます。

#  Load shape into gdal
shapefile=str(vectorPath)
layer_source = ogr.Open(shapefile)
lyr = layer_source.GetLayer(0)
for i in range(0,lyr.GetFeatureCount()):
     feat = lyr.GetFeature(i)
     ge = feat.geometry()

このジオメトリに基づいてosgeo.ogr.layerオブジェクトを作成する方法を知る必要があります。


明確にするために。プレーンogr / gdalコードの関数が必要です!これは他の人にも興味があるようであり、セカンダリモジュールなしのソリューションが引き続き必要です(ただし、ここから来るソリューションは無料のqgis​​プラグインで使用されます)。

回答:


7

それでは、純粋なGDALソリューションを使用して2回目の質問に答えてみてください。

まず、GDAL(Geospatial Data Abstraction Library)はもともとラスター地理空間データを操作するためのライブラリでしたが、別のOGRライブラリはベクターデータを操作するためのものでした。ただし、2つのライブラリーは現在部分的にマージされており、通常はGDALの結合名で一緒にダウンロードおよびインストールされます。そのため、ソリューションは本当にOGRに該当します。最初のコードにこれがあるので、知っていたと思いますが、ヒントやヒントを検索する際に覚えておくべき重要な違いです。

ベクターレイヤーからデータを読み取るには、最初のコードで十分です。

from osgeo import ogr
shapefile = ogr.Open(shapefile)
layer = shapefile.GetLayer(0)

for i in range(layer.GetFeatureCount()):
    feature = layer.GetFeature(i)
    name = feature.GetField("NAME")
    geometry = feature.GetGeometryRef()
    print i, name, geometry.GetGeometryName()

シェープファイル(またはその他のベクターデータセット)に書き込む前に、新しい機能を作成する必要があります。新しいフィーチャを作成するには、最初に次のものが必要です。-ジオメトリ-おそらくフィールド定義を含むフィーチャ定義Geometryコンストラクタogr.Geometry()を使用して空のGeometryオブジェクトを作成します。タイプ(ポイント、ライン、ポリゴンなど)ごとに異なる方法でジオメトリを定義します。たとえば、次のとおりです。

point = ogr.Geometry(ogr.wkbPoint)
point.AddPoint(10,20)

または

line = ogr.Geometry(ogr.wkbLineString)
line.AddPoint(10,10)
line.AddPoint(20,20)
line.SetPoint(0,30,30) #(10,10) -> (30,30)

フィールド定義用

fieldDefn = ogr.FieldDefn('id', ogr.OFTInteger)

これで、ベクターレイヤーを作成できます。この例では、正方形のポリゴンは次のとおりです。

#create simple square polygon shapefile:
from osgeo import ogr
driver = ogr.GetDriverByName('ESRI Shapefile')

datasource = driver.CreateDataSource('YOUR_PATH')
layer = datasource.CreateLayer('layerName',geom_type=ogr.wkbPolygon)

#create polygon object:
myRing = ogr.Geometry(type=ogr.wkbLinearRing)
myRing.AddPoint(0.0, 0.0)     #LowerLeft
myRing.AddPoint(0.0, 10.0)    #UpperLeft
myRing.AddPoint(10.0, 10.0)   #UpperRight
myRing.AddPoint(10.0, 0.0)    #Lower Right
myRing.AddPoint(0.0, 0.0)     #close ring
myPoly = ogr.Geometry(type=ogr.wkbPolygon)
myPoly.AddGeometry(myRing)
print ('Polygon area =',myPoly.GetArea())  #returns correct area of 100.0

#create feature object with point geometry type from layer object:
feature = ogr.Feature( layer.GetLayerDefn())
feature.SetGeometry(myPoly)
layer.CreateFeature(feature)

#flush memory - very important
feature.Destroy()
datasource.Destroy()

ありがとうダン!別のアプローチを取り、QGISプラグインは既に機能しています(ラスターデータの空間クエリに関して)。分割する代わりに、基になるラスターのサブセットを作成しました。ユースケースは私のブログ(tinyurl.com/cy6hs9q)で見つけることができます。ベクトルの特徴を分割して一時的に保存したい場合、あなたの答えは元の質問を解決します。
Curlew

5

レイヤーからの読み取りと書き込みがうまくできました。具体的には、ポリラインを含むシェープファイルレイヤーを読み取り、各フィーチャのジオメトリをテキストファイルに出力するコードがあります(古いモデルの入力として使用)。

name     = layer.name()
provider = layer.dataProvider()
feat     = QgsFeature()

# Now we can loop through all the defined features
while provider.nextFeature(feat):

    # Get layer attributes               
    attrs = feat.attributeMap()
    for (k,attr) in attrs.iteritems():
        if k == 0:
            attrOne = attr.toString()
        elif k == 1:
            attrTwo = attr.toString()
        ...

    # Gets the geometry of the feature
    geom = feat.geometry()

    # Get the coordinates of the whole line [or use asPoint()]                    
    line = geom.asPolyline()
        # all points in the line
        for point in line:
            lat = point[0]
            lon = point[1]
            # Add these to a QgsGeometry
            your_Own_QgsGeometry.add...

これは、レイヤーから各フィーチャを取得するのに役立つと思われます。

ここから別のレイヤーへの書き込みが複雑になってはいけません。このようなものは理論的には機能するはずです:

# New layer name
filename = "myNewLayer.shp"

# define fields for feature attributes
fields   = { 0 : QgsField("attrOne", QVariant.String),
             1 : QgsField("attrTwo", QVariant.String),
             2 : QgsField("...", QVariant.Int) }

# Create coordinate reference system as WGS84
crs    = QgsCoordinateReferenceSystem(4326, QgsCoordinateReferenceSystem.PostgisCrsId)

# Create the vector layer
writer = QgsVectorFileWriter(filename, "CP1250", fields, QGis.WKBLineString, crs)

# Create some features
feat = QgsFeature()
feat.addAttribute(0, QVariant(runway))
feat.addAttribute(1, QVariant(arriveDepart))
feat.addAttribute(2, QVariant(subTrack))

# Add your geometry
feat.setGeometry(your_Own_QgsGeometry)

# Add the features
writer.addFeature(feat)

# Add it to QGIS project
self.iface.addVectorLayer(filename, "MyLayerName", "ogr")

ここから、各フィーチャのデータを取得し、新しいフィーチャを新しいレイヤーに書き込むことができるはずです。

ダン


ねえ、ありがとう。図形に属性を書き込みたい場合、コードの一部が役立ちます。ただし、上記で述べたように、gdal(具体的にはgdal.RasterizeFunction)のみを使用しており、QgsVectorLayerオブジェクトをgdalオブジェクトに、またはその逆に変換する方法を誰かが知らない限り、この問題は未解決のままです。
Curlew

QGISでこれを行う必要があることは言及しませんでした。最初の例は単純なバニラogrのようです。
-DavidF

QGISでこれをしたい(QGISプラグインの機能として必要)が、QGIS.coreモジュールに依存せずに。したがって、プレーンogrのソリューションが必要です。Danは別の投稿でこのコードはQGISプラグイン用であると述べたので答えました。
-18:
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.