Tách shapefile cho mỗi tính năng trong Python bằng GDAL?


14

Có thể phân chia một shapefile cho mỗi tính năng trong python? (tốt nhất sẽ là một giải pháp trong đó tôi có thể tạm thời lưu các đối tượng vector kết quả vào bộ nhớ thay vào đĩa).

Lý do: Tôi muốn sử dụng hàm gdal rasterizeLayer với một số tập con khác nhau của shapefile. Hàm này yêu cầu một đối tượng osgeo.ogr.Layer.


mkay, tôi đã thử một chút xung quanh và nó có thể hoạt động như sau. Bạn có thể nhận được hình dạng của các đối tượng lớp gdal cho mỗi tính năng như sau.

#  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()

Bây giờ tôi chỉ cần biết làm thế nào để tạo một đối tượng osgeo.ogr.layer dựa trên hình học này.


Để làm rõ. Tôi cần một hàm trong mã ogr / gdal đơn giản! Điều này dường như cũng được người khác quan tâm và tôi vẫn muốn một giải pháp mà không cần bất kỳ mô-đun thứ cấp nào (mặc dù mọi giải pháp đến từ đây sẽ được sử dụng trong một plugin qgis miễn phí).

Câu trả lời:


7

OK, vì vậy một nỗ lực thứ hai để trả lời câu hỏi của bạn với một giải pháp GDAL thuần túy.

Đầu tiên, GDAL (Thư viện trừu tượng dữ liệu không gian địa lý) ban đầu chỉ là một thư viện để làm việc với dữ liệu không gian địa lý raster, trong khi thư viện OGR riêng biệt được dự định để làm việc với dữ liệu vectơ. Tuy nhiên, hai thư viện hiện đã được hợp nhất một phần và thường được tải xuống và cài đặt cùng nhau dưới tên kết hợp của GDAL. Vì vậy, giải pháp thực sự thuộc OGR. Bạn có mã này trong mã ban đầu của bạn vì vậy tôi đoán bạn đã biết điều này nhưng đó là một điểm khác biệt quan trọng cần nhớ khi tìm kiếm các mẹo và gợi ý.

Để đọc dữ liệu từ một lớp vectơ, mã ban đầu của bạn vẫn ổn:

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()

Chúng ta cần tạo một tính năng mới trước khi có thể ghi nó vào shapefile (hoặc bất kỳ tập dữ liệu vectơ nào khác). Để tạo một tính năng mới, trước tiên chúng ta cần: - Hình học - Một định nghĩa tính năng, có thể sẽ bao gồm các định nghĩa trường Sử dụng hàm tạo Hình học ogr.Geometry () để tạo một đối tượng Hình học trống. Xác định hình học là gì theo một cách khác nhau cho từng loại (điểm, đường, đa giác, v.v.). Ví dụ:

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

hoặc là

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

Đối với một định nghĩa trường

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

Bây giờ bạn có thể tạo lớp vector của bạn. Trong trường hợp này, một đa giác vuông:

#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()

cảm ơn Dân! Tôi đã thực hiện một cách tiếp cận khác và plugin QGIS của tôi đã có thể hoạt động được (liên quan đến các truy vấn không gian của dữ liệu raster). Thay vì chia tách, tôi đã tạo một tập hợp con của raster bên dưới. Bạn có thể tìm thấy một trường hợp sử dụng trên blog của tôi ( tinyurl.com/cy6hs9q ). Câu trả lời của bạn giải quyết câu hỏi ban đầu, nếu tôi muốn tách và tạm thời lưu các tính năng vector.
Curlew

5

Tôi đã có một số may mắn đọc từ và viết lên các lớp. Cụ thể, tôi có mã sẽ đọc một lớp shapefile chứa polylines và xuất hình học của từng tính năng thành các tệp văn bản (được sử dụng làm đầu vào cho một mô hình cũ).

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...

Điều này có vẻ hữu ích để có được từng tính năng từ các lớp của bạn.

Viết cho một lớp khác không nên quá phức tạp từ đây. Một cái gì đó như thế này sẽ hoạt động trên lý thuyết:

# 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")

Từ đây bạn sẽ có thể lấy dữ liệu của từng tính năng từ và viết các tính năng mới sang một lớp mới.

Dân


này cảm ơn nhé. Các phần trong mã của bạn sẽ hữu ích, nếu tôi muốn viết các thuộc tính cho hình dạng của mình. Tuy nhiên như tôi đã đề cập ở trên, tôi chỉ sử dụng gdal (cụ thể là gdal.RasterizeFunction) và trừ khi có ai đó biết cách chuyển đổi một đối tượng QssVectorLayer thành một đối tượng gdal và ngược lại, câu hỏi này vẫn chưa được giải quyết.
Curlew

Bạn đã không đề cập rằng bạn cần phải làm điều này với QGIS. ví dụ ban đầu của bạn dường như là vanilla ogr đơn giản.
DavidF

tôi muốn thực hiện điều này trong QGIS (tôi cần nó như là một chức năng cho plugin QGIS), nhưng không phụ thuộc vào các mô-đun QGIS.core. Vì vậy, tôi cần các giải pháp trong đồng bằng ogr. Dan trả lời vì tôi đã đề cập trong một bài đăng khác rằng mã này dành cho plugin QGIS.
Curlew
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.