使用GDAL在Python中按功能分割shapefile?


15

是否有可能在python中按功能分割一个shapefile?(最好是将临时生成的矢量对象临时保存到内存而不是磁盘的解决方案)。

原因:我想将gdal rasterizeLayer函数与shapefile的几个不同子集一起使用。该函数需要一个osgeo.ogr.Layer对象。


mkay,我尝试了一下,它可能如下工作。您可以按以下方式获取每个要素的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插件中使用)。

Answers:


7

好的,第二次尝试使用纯GDAL解决方案来回答您的问题。

首先,GDAL(地理空间数据抽象库)最初只是一个用于处理栅格地理空间数据的库,而单独的OGR库则旨在用于矢量数据。但是,这两个库现在已部分合并,并且通常以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()

我们需要先创建一个新功能,然后才能将其写入shapefile(或任何其他矢量数据集)。要创建新特征,我们首先需要:-几何-特征定义,其中可能包含字段定义。使用几何构造函数ogr.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

我在读和写图层时有些运气。具体来说,我有代码将读取包含折线的shapefile图层,并将每个要素的几何输出到文本文件(用作旧模型的输入)。

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 2012年

您没有提到您需要使用QGIS进行此操作。您最初的例子似乎是普通香草味。
DavidF 2012年

我想在QGIS中执行此操作(我需要将其作为QGIS插件的功能),但又不依赖QGIS.core模块。因此,我需要简单的解决方案。Dan回答是因为我在另一篇文章中提到此代码是针对QGIS插件的。
Curlew
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.