Разделить шейп-файл на объект в Python с помощью GDAL?

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.

Во-первых, 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()

Нам нужно создать новую функцию, прежде чем мы сможем записать ее в шейп-файл (или любой другой набор векторных данных). Для создания нового объекта нам сначала необходимо: - Геометрия - Определение объекта, которое, вероятно, будет включать определения полей. Используйте конструктор 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 и наоборот, этот вопрос все еще не решен.
Керлью
Вы не упомянули, что вам нужно сделать это с QGIS. Ваш первоначальный пример выглядит как простой ванильный огр.
DavidF
Я хочу сделать это в QGIS (мне нужно это как функция для плагина QGIS), но не полагаясь на модули QGIS.core. Поэтому мне нужно решение в простой огр. Дэн ответил, потому что я упоминал в другом посте, что этот код предназначен для плагина QGIS.
Керлью